【洛谷】1821 [USACO07FEB]銀牛派對Silver Cow Party 最短路徑
阿新 • • 發佈:2019-02-06
日常水一波,就是對正向圖跑一遍SPFA,然後建一張反向圖,也就是求其他所有的節點到源點的距離,然後再跑一遍SPFA。
最後輸出兩次距離和的最大值就行了。
附上AC程式碼:
#include <cstdio> #include <cctype> #include <queue> #include <cstring> #define M 100010 #define N 1010 using namespace std; struct note{ int to,w,nt; }z[M*2],f[M*2]; int n,m,st,num,hz[N],hf[N],x,y,w,d1[N],d2[N]; long long ans; queue <int> que; bool b[N]; void read(int& a){ static char c=getchar();a=0;int f=1; while (!isdigit(c)) {if (c=='-') f=-1;c=getchar();} while (isdigit(c)) a=a*10+c-'0',c=getchar(); a*=f;return; } void add(int x,int y,int w){ z[num]=(note){x,w,hz[y]}; f[num]=(note){y,w,hf[x]}; hz[y]=hf[x]=num++; } void spfa1(){ while (!que.empty()) que.pop(); memset(b,0,sizeof b); memset(d1,0x3f,sizeof d1); que.push(st),d1[st]=0,b[st]=1; while (!que.empty()){ int p=que.front();que.pop(),b[p]=0; for (int i=hz[p]; ~i; i=z[i].nt) if (d1[z[i].to]>d1[p]+z[i].w){ d1[z[i].to]=d1[p]+z[i].w; if (!b[z[i].to]){ b[z[i].to]=1; que.push(z[i].to); } } } return; } void spfa2(){ while (!que.empty()) que.pop(); memset(b,0,sizeof b); memset(d2,0x3f,sizeof d2); que.push(st),d2[st]=0,b[st]=1; while (!que.empty()){ int p=que.front();que.pop(),b[p]=0; for (int i=hf[p]; ~i; i=f[i].nt) if (d2[f[i].to]>d2[p]+f[i].w){ d2[f[i].to]=d2[p]+f[i].w; if (!b[f[i].to]){ b[f[i].to]=1; que.push(f[i].to); } } } return; } int main(void){ read(n),read(m),read(st); memset(hz,-1,sizeof hz),memset(hf,-1,sizeof hf); for (int i=1; i<=m; ++i) read(x),read(y),read(w),add(x,y,w); spfa1(),spfa2(); for (int i=1; i<=n; ++i) ans=max(ans,(long long)d1[i]+d2[i]); printf("%lld",ans); return 0; }