P1821 [USACO07FEB]银牛派对Silver Cow Party
最短路Dijkstra
十分显然地,做两遍最短路。
原图跑一遍(出行),反向图跑一遍(归程)。把每个点的2次最短路的结果之和拿来做比较即可。
#include<iostream> #include<cstdio> #include<cstring> #include<cctype> #include<queue> using namespace std; template <typename T> inline T max(T &a,T &b) {return a>b ?a:b;} template <typename T> inline void read(T &x){ char c=getchar(); x=0; while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar(); } struct data{ int d,u; bool operator < (const data &tmp) const{return d>tmp.d;} }; int n,m,s,cnt[2],d[2][1002],hd[2][1002],nxt[2][100002],ed[2][100002],poi[2][100002],val[2][100002]; inline void add(int x,int y,int v,int p){ nxt[p][ed[p][x]]=++cnt[p]; hd[p][x]= hd[p][x] ? hd[p][x]:cnt[p]; ed[p][x]=cnt[p]; poi[p][cnt[p]]=y; val[p][cnt[p]]=v; } void dijkstra(int p){ memset(d[p],127,sizeof(d[p])); priority_queue <data> h; h.push((data){d[p][s]=0,s}); while(!h.empty()){ data x=h.top(); h.pop(); if(x.d!=d[p][x.u]) continue; for(int i=hd[p][x.u];i;i=nxt[p][i]) if(d[p][x.u]+val[p][i]<d[p][poi[p][i]]){ d[p][poi[p][i]]=d[p][x.u]+val[p][i]; h.push((data){d[p][poi[p][i]],poi[p][i]}); } } } int main(){ read(n); read(m); read(s); int q1,q2,q3; for(int i=1;i<=m;++i) read(q1),read(q2),read(q3),add(q1,q2,q3,0),add(q2,q1,q3,1); //建正/反向图 dijkstra(0); dijkstra(1); int ans=0; //正反图各跑一遍最短路 for(int i=1;i<=n;++i) ans=max(ans,d[0][i]+d[1][i]); //比较两次权值之和,即为最长的最短路 printf("%d",ans); return 0; }