题意:给出一个图,要你构出最短路树
题解:
spfa
和上次那个题一样,一条边只会松弛一个点,spfa的同时记录每个点被哪条边松弛
将这些边加入答案即可
注意一下边的范围,没long long,wa了几次......
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<algorithm> 6 #include<cmath> 7 #include<queue> 8 #define ll long long 9 using namespace std; 10 11 const int N = 300010; 12 13 ll ans=0,dis[N]; 14 int n,m,e_num,s; 15 int nxt[N*2],to[N*2],w[N*2],h[N],pre[N]; 16 bool in[N]; 17 18 queue<int> q; 19 20 inline int gi() { 21 int x=0,o=1; char ch=getchar(); 22 while(ch!=‘-‘ && (ch<‘0‘ || ch>‘9‘)) ch=getchar(); 23 if(ch==‘-‘) o=-1,ch=getchar(); 24 while(ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar(); 25 return o*x; 26 } 27 28 inline void add(int x, int y, int z) { 29 nxt[++e_num]=h[x],to[e_num]=y,w[e_num]=z,h[x]=e_num; 30 } 31 32 inline void spfa() { 33 memset(dis,63,sizeof(dis)); 34 dis[s]=0,in[s]=1,q.push(s); 35 while(!q.empty()) { 36 int u=q.front(); 37 in[u]=0,q.pop(); 38 for(int i=h[u]; i; i=nxt[i]) { 39 int v=to[i]; 40 if(dis[u]+w[i]<dis[v]) { 41 pre[v]=i; 42 dis[v]=dis[u]+w[i]; 43 if(!in[v]) in[v]=1,q.push(v); 44 } 45 else if(dis[u]+w[i]==dis[v]) { 46 if(w[i]<w[pre[v]]) pre[v]=i; 47 } 48 } 49 } 50 } 51 52 int main() { 53 n=gi(),m=gi(); 54 for(int i=1; i<=m; i++) { 55 int x=gi(),y=gi(),z=gi(); 56 add(x,y,z),add(y,x,z); 57 } 58 s=gi(),spfa(); 59 for(int i=1; i<=n; i++) { 60 if(i==s) continue; 61 ans+=w[pre[i]]; 62 } 63 printf("%lld\n", ans); 64 return 0; 65 }
时间: 2024-10-20 12:16:29