題解 CF545E 【Paths and Trees】
阿新 • • 發佈:2020-11-24
思路:
\(\quad\)只需要以題目給定的 \(u\) 為起點跑一遍 \(Dijkstra\) 最短路即可,每次記錄每個點的前驅(即到達這個點的邊),注意有多個可以選擇的邊中選擇邊權最小的,感覺很像一個最小生成樹,最後記得要記錄樹上的邊權並排序再輸出,起點 \(u\) 是沒有前驅的,所以要從 \(2\) 開始輸出。
\(\quad\)如果還不能理解就看看程式碼吧,有一些關鍵的註釋。
#include<iostream> #include<cstdio> #include<cmath> #include<string> #include<algorithm> #include<map> #include<queue> #include<stack> #include<cstring> using namespace std; #define re register int #define int long long #define LL long long #define il inline #define next nee #define inf 1e18 il int read() { int x=0,f=1;char ch=getchar(); while(!isdigit(ch)&&ch!='-')ch=getchar(); if(ch=='-')f=-1,ch=getchar(); while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar(); return x*f; } il void print(int x) { if(x<0)putchar('-'),x=-x; if(x/10)print(x/10); putchar(x%10+'0'); } const int N=3e5+5; int n,m,next[N<<1],go[N<<1],head[N],tot,dis[N],s[N<<1],t,du[N],ans; bool b[N]; il void Add(int x,int y,int z) { next[++tot]=head[x];head[x]=tot; go[tot]=y;s[tot]=z; } struct node{ int pos,dis; il bool operator<(const node &x)const {return dis>x.dis;} }; priority_queue<node>q; il void Dijkstra(int p)//板子Dijkstra { for(re i=1;i<=n;i++)dis[i]=inf;dis[p]=0; q.push((node){p,0}); while(!q.empty()) { node tmp=q.top();q.pop(); int x=tmp.pos; if(b[x])continue; b[x]=1; for(re i=head[x];i;i=next[i]) { int y=go[i]; if(dis[y]>dis[x]+s[i]) { du[y]=i;//du記錄前驅編號為i的邊 dis[y]=dis[x]+s[i]; q.push((node){y,dis[y]}); } else if(dis[y]==dis[x]+s[i])//有多條最短路徑時 {if(s[du[y]]>s[i])du[y]=i;}//選擇邊權小的 } } } signed main() { n=read();m=read(); for(re i=1;i<=m;i++) {re x=read(),y=read(),z=read();Add(x,y,z);Add(y,x,z);} t=read(); Dijkstra(t); for(re i=1;i<=n;i++)ans+=s[du[i]];//ans統計答案 for(re i=1;i<=n;i++)dis[i]=du[i]+1>>1; sort(dis+1,dis+n+1);//別忘了排序 print(ans);putchar('\n'); for(re i=2;i<=n;i++)print(dis[i]),putchar(' ');//從2開始輸出 return 0; }