洛谷 P1342
思路
分别建一张原图,一张与原图中所有边方向相反的反图。在两张图上分别跑一遍SPFA,再计算出两次dis数组的和即可。
Code
#include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<queue> typedef long long LL; #define maxn 1000005 using namespace std; int n,m; int pre1[maxn],last1[maxn],other1[maxn],len1[maxn],tot1; int pre2[maxn],last2[maxn],other2[maxn],len2[maxn],tot2; int dis1[maxn],dis2[maxn]; bool vis1[maxn],vis2[maxn]; inline void add1(int x,int y,int z){ tot1++; pre1[tot1]=last1[x]; last1[x]=tot1; other1[tot1]=y; len1[tot1]=z; } inline void add2(int x,int y,int z){ tot2++; pre2[tot2]=last2[x]; last2[x]=tot2; other2[tot2]=y; len2[tot2]=z; } void spfa1(int s){ queue<int>q; memset(dis1,0x3f,sizeof(dis1)); q.push(s); dis1[s]=0; vis1[s]=1; while(!q.empty()){ int u=q.front(); q.pop(); vis1[u]=0; for(register int p=last1[u];p;p=pre1[p]){ int v=other1[p]; if(dis1[v]>dis1[u]+len1[p]){ dis1[v]=dis1[u]+len1[p]; if(!vis1[v]){ q.push(v); vis1[v]=1; } } } } } void spfa2(int s){ queue<int>q; memset(dis2,0x3f,sizeof(dis2)); q.push(s); dis2[s]=0; vis2[s]=1; while(!q.empty()){ int u=q.front(); q.pop(); vis2[u]=0; for(register int p=last2[u];p;p=pre2[p]){ int v=other2[p]; if(dis2[v]>dis2[u]+len2[p]){ dis2[v]=dis2[u]+len2[p]; if(!vis2[v]){ q.push(v); vis2[v]=1; } } } } } int main(){ scanf("%d%d",&n,&m); for(register int i=1;i<=m;i++){ int x,y,z; scanf("%d%d%d",&x,&y,&z); add1(x,y,z); add2(y,x,z); } spfa1(1); spfa2(1); LL ans=0; for(register int i=1;i<=n;i++) ans+=dis1[i]+dis2[i]; printf("%lld",ans); }