1. 程式人生 > >[題解] P1342 請柬

[題解] P1342 請柬

spf emp spa tps pri 題解 bsp ref namespace

洛谷 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); }

[題解] P1342 請柬