传送门:(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;
}