题意 求一个生成树,使得任意点到源点的最短路等于原图中的最短路。再让这个生成树边权和最小。 http://codeforces.com/contest/545/problem/E 思路 先Dijkstra一下,再对每个点连的边判断是不是
题意
求一个生成树,使得任意点到源点的最短路等于原图中的最短路。再让这个生成树边权和最小。
http://codeforces.com/contest/545/problem/E
思路
先Dijkstra一下,再对每个点连的边判断是不是最短路上的边,如果是那再贪心取最小的边即可。
代码
#include<bits/stdc++.h> using namespace std; #define ll long long const ll inf=1e18; const int N=6e5+5; struct qnode { ll v; ll c; qnode(ll _v=0,ll _c=0):v(_v),c(_c){} bool operator <(const qnode &r)const { return c>r.c; } }; struct edge { ll v,cost; int next; }; edge eg[N]; int head[N]; ll dist[N],tot=1; bool vis[N]; void Dijkstra(int n,int sta) { memset(vis,false,sizeof(vis)); for(int i=1;i<=n;i++) dist[i]=inf; priority_queue<qnode> pq; dist[sta]=0; pq.push(qnode(sta,0)); qnode tmp; while(!pq.empty()) { tmp=pq.top(); pq.pop(); int u=tmp.v; if(vis[u])continue; vis[u]=true; for(int i=head[u];~i;i=eg[i].next) { int v=eg[i].v; int cost=eg[i].cost; if(!vis[v]&&dist[v]>dist[u]+cost) { dist[v]=dist[u]+cost; pq.push(qnode(v,dist[v])); } } } } void init() { memset(head,-1,sizeof(head)); tot=1; } void addedge(int u,int v,ll w) { eg[tot].v=v; eg[tot].cost=w; eg[tot].next=head[u]; head[u]=tot++; } int main() { int n,m; init(); scanf("%d%d",&n,&m); for(int i=0;i<m;i++) { int u,v; ll w; scanf("%d%d%lld",&u,&v,&w); addedge(u,v,w); addedge(v,u,w); } int rt; scanf("%d",&rt); Dijkstra(n,rt); vector<int> ans; ll sum=0; for(int i=1;i<=n;i++) { if(i!=rt) { ll mn=inf,mi; for(int j=head[i];~j;j=eg[j].next) { int v=eg[j].v; if(dist[i]==dist[v]+eg[j].cost) { if(mn>eg[j].cost) { mn=eg[j].cost; mi=(j+1)/2; } } } ans.push_back(mi); sum+=mn; } } printf("%lld\n",sum); for(int i : ans) { printf("%d ",i); } puts(""); return 0; }