【题解: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;
} 

猜你喜欢

转载自blog.csdn.net/qq_43263852/article/details/85460269