POJ3268 Silver Cow Party【Dijkstra算法+思维】

Silver Cow Party

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 30185   Accepted: 13703

Description

One cow from each of N farms (1 ≤ N ≤ 1000) conveniently numbered 1..N is going to attend the big cow party to be held at farm #X (1 ≤ X ≤ N). A total of M (1 ≤ M ≤ 100,000) unidirectional (one-way roads connects pairs of farms; road i requires Ti (1 ≤ Ti ≤ 100) units of time to traverse.

Each cow must walk to the party and, when the party is over, return to her farm. Each cow is lazy and thus picks an optimal route with the shortest time. A cow's return route might be different from her original route to the party since roads are one-way.

Of all the cows, what is the longest amount of time a cow must spend walking to the party and back?

Input

Line 1: Three space-separated integers, respectively: NM, and X 
Lines 2..M+1: Line i+1 describes road i with three space-separated integers: AiBi, and Ti. The described road runs from farm Ai to farm Bi, requiring Titime units to traverse.

Output

Line 1: One integer: the maximum of time any one cow must walk.

Sample Input

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

Sample Output

10

Hint

Cow 4 proceeds directly to the party (3 units) and returns via farms 1 and 3 (7 units), for a total of 10 time units.

Source

USACO 2007 February Silver

问题链接:POJ3268 Silver Cow Party

问题描述:有m条单向边连接着 n个农场(从1开始编号),每个农场都会派出一个奶牛去X号农场参加派对,派对结束后再返回各自的农场。求奶牛们的最短路径的最大值。

解题思路:奶牛i需要的最短时间=i到x的最短时间+x到i的最短时间。前者好求,可以使用dijkstra算法,后者要先将邻接矩阵转置再执行最短路算法:u(u != x)到x的最短路为<u,v1>,<v1,v2>,<v2,v3>,...,<vi, x>,这条路径在转置邻接矩阵后变成<x,vi>,...,<v3,v2>,<v2, v1>,<v1,u>.于是,在转置邻接矩阵后,执行最短路算法求出x到u的最短路<x,vi>,...,<v3,v2>,<v2, v1>,<v1,u>即可得到转置前u到x的最短路。

AC的C++代码:

#include<iostream>
#include<queue>
#include<cstring> 
#include<vector>
 
using namespace std;
 
const int INF=((unsigned int)(-1)>>1);//2^31-1
const int N=1005;
 
struct Node{//表示结点的结构体 
	int u,cost;//表示此刻源点到结点u的最短路径为cost 
	Node(){}
	Node(int u,int cost):u(u),cost(cost){}
	bool operator<(const Node &a)const//按照此刻源点到结点v的最短距离从小到大排序 
	{
		return cost>a.cost;//由于使用优先队列故重载为大于含义 
	} 
};
 
int g[N][N];//邻接矩阵 
int rg[N][N];
int dist[N];//记录源点到个结点的最短路径
int ans[N];
bool vis[N];//记录源点到结点i的最短路径是否已经找到
 
void dijkstra(int s,int n)//源点编号是s,共有n个结点 
{
	priority_queue<Node>q;
	for(int i=1;i<=n;i++){//初始化 
		dist[i]=INF;
		vis[i]=false;
	}
	dist[s]=0;//源点到源点的距离是0
	q.push(Node(s,0));
	while(!q.empty()){
		Node e=q.top();
		q.pop();
		int u=e.u;//此结点的最短路以找到
		if(!vis[u]){
			vis[u]=true;
			for(int i=1;i<=n;i++){
				if(g[u][i]==INF)
				  continue;
				int temp=dist[u]+g[u][i];
				if(temp<dist[i]){
					dist[i]=temp;
					q.push(Node(i,temp));
				} 
			} 
		} 
	} 
}
 
int main()
{
	int n,m,x,a,b,t;
	while(scanf("%d%d%d",&n,&m,&x)!=EOF){
		for(int i=1;i<=n;i++)
		  for(int j=1;j<=n;j++)
		    g[i][j]=(i==j)?0:INF;
		while(m--){
			scanf("%d%d%d",&a,&b,&t);
			if(g[a][b]>t)
			  g[a][b]=t;
		}
		//求x到各个点的最短路 
		dijkstra(x,n);
		memcpy(ans,dist,sizeof(dist));//保存x到各个点的最短路
		//转置g
		memcpy(rg,g,sizeof(g));
		for(int i=1;i<=n;i++)
		  for(int j=1;j<=n;j++)
		    g[i][j]=rg[j][i];
	    //求各个点到x的最短路 
		dijkstra(x,n);
		int res=0;
		for(int i=1;i<=n;i++){
			ans[i]+=dist[i];
			if(ans[i]<INF&&ans[i]>res)
			  res=ans[i];
		}
		printf("%d\n",res);
	}
	return 0; 
}
 
 

猜你喜欢

转载自blog.csdn.net/SongBai1997/article/details/83111413