POJ3268 Silver Cow Party【Dijkstra演算法+思維】

Enjoy_process發表於2018-10-17

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; 
}
 
 

 

相關文章