【題解:POJ3268 Silver Cow Party】(最短路問題)
傳送門:(http://poj.org/problem?id=3268)
題目描述:
農場有N(1≤N≤1000)個牛棚,每個牛棚都有1只奶牛要參加在X牛棚舉行的奶牛派對.共有M(1≤M≤100000)條單向路連線著牛棚,第i條踣需要Ti的時間來通過.牛們都很懶,所以不管是前去X牛棚參加派對還是返回住所,她們都採用了用時最少的路線.那麼,用時最多的奶牛需要多少時間來回呢?
輸入
第1行:三個用空格隔開的整數n,m,x. 第2行到第M+1行,每行三個用空格隔開的整數:Ai, Bi,以及Ti.表示一條道路的起點,終點和需要花費的時間.
輸出
唯一一行:一個整數: 所有參加聚會的奶牛中,需要花費總時間的最大值.
樣例輸入
4 8 2
1 2 4
1 3 2
1 4 7
2 1 1
2 3 5
3 1 2
3 4 4
4 2 3
樣例輸出
10
讀完題很容易發現這是一道最短路問題,只需找到節點i—>節點x的最短路,再找到節點x—>節點i的最短路,兩次spfa的結果相加就可得到節點i總共需要的時間,最後排序或者打擂臺就OK了。
x到i的距離很好求,直接spfa就好,關鍵是i到x的距離。
難道是做n次最短路,分別求出i到x的最短路?動動腳指頭上角質層的最外面的那一小塊,也知道不行啊。
還是那句老話啊,正難則反,正難則反,正難則反。
既然每一次spfa都是以x為終點的,那為何不反向建圖,做一個以x為起點的單源最短路呢?
所以流程就很清楚了。
step1:讀入
step2:建圖,注意建兩次,一次正向一次反向,也就是建兩張圖。
step3:兩次spfa,在原圖中找到奶牛返程所需的時間,在返圖中找到奶牛出程所需的時間。
step4:1~n跑一遍,求出每頭奶牛的總耗時,然後排序(或打擂臺)。
step5:輸出。
貼程式碼:
#include<iostream> #include<algorithm> #include<queue> #include<vector> #include<cstring> #include<cstdio> using namespace std; inline int read(){ int ans,flag=1; char ch; while((ch=getchar())<'0'||ch>'9') if(ch=='-') flag=-1; ans=ch-48; while((ch=getchar())>='0'&&ch<='9') ans=ans*10+ch-48; return ans*flag; } int n,m,x; int vis[3][1001],dis[3][1001]; int head[1001],Head[1001],cnt=0,num=0; int ans[1001]; struct node{ int u,v,w,nt; }e[1000001],E[1000001]; inline void add1(int u,int v,int w){ cnt++; e[cnt].u=u,e[cnt].v=v,e[cnt].w=w; e[cnt].nt=head[u],head[u]=cnt; } inline void add2(int u,int v,int w){ num++; E[num].u=u,E[num].v=v,E[num].w=w; E[num].nt=Head[u],Head[u]=num; } void spfa1(int x){ memset(vis[1],0,sizeof(vis[1])); memset(dis[1],0x3f,sizeof(dis[1])); dis[1][x]=0;vis[1][x]=1; queue<int> q; q.push(x); while(!q.empty()){ int u=q.front();q.pop(); vis[1][u]=0; for(int i=head[u];i;i=e[i].nt){ int v=e[i].v; if(dis[1][v]>dis[1][u]+e[i].w){ dis[1][v]=dis[1][u]+e[i].w; if(!vis[1][v]) q.push(v) ,vis[1][v]=1; } } } } void spfa2(int x){ memset(vis[2],0,sizeof(vis[2])); memset(dis[2],0x3f,sizeof(dis[2])); dis[2][x]=0;vis[2][x]=1; queue<int> q; q.push(x); while(!q.empty()){ int u=q.front();q.pop(); vis[2][u]=0; for(int i=Head[u];i;i=E[i].nt){ int v=E[i].v; if(dis[2][v]>dis[2][u]+E[i].w){ dis[2][v]=dis[2][u]+E[i].w; //cout<< if(!vis[2][v]) { q.push(v) ,vis[2][v]=1; } } } } } int main(){ n=read(),m=read(),x=read(); int u,v,w; while(m--){ u=read(),v=read(),w=read(); add1(v,u,w); add2(u,v,w); } spfa1(x),spfa2(x); for(int i=1;i<=n;i++) ans[i]=dis[1][i]+dis[2][i]; int ret=-1; for(int i=1;i<=n;i++) if(ans[i]>ret) ret=ans[i]; cout<<ret; //cout<<ret<<" "<<id<<endl; //cout<<dis[1][id]<<" "<<dis[2][id]; return 0; }