POJ3268 Silver Cow Party Dijkstra最短路
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
Lines 2.. M+1: Line i+1 describes road i with three space-separated integers: Ai, Bi, and Ti. The described road runs from farm Ai to farm Bi, requiring Ti time units to traverse.
Output
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
题意:
有编号为1-N的牛,它们之间存在一些单向的路径。给定一头牛的编号,其他牛要去拜访它并且拜访完之后要返回自己原来的位置,求这些牛中所花的最长的来回时间是多少。
输入第一行n,m,x 表示n头牛 m条路 起点x
思路:
每头牛返回的最短时间很简单就可以算出来,这相当于从目标牛为起点求单源最短路径。
但每头牛出发到目标牛的最短时间无法直接算出来,稍微转换一下,发现这个最短时间其实可以通过把矩阵转置,然后再从目标牛求一次单源最短路径得到。
得到这两个最短路径之后,取它们的和的最大者即可。
转置:假如起点是1,从1到2是2km,从2到1是3km,回来的时候是从1到2是2km,这个不用转置。去的时候从2到1是3km,转置后从1到2是3km,从2到1是2km,我们要的是从1到2这一个。
代码:
#include<cstdio> #include<cstring> #include<algorithm> #define MAX 0x3f3f3f3f using namespace std; int map[2000][2000];//矩阵存储信息 int n,m,s; int come[2000],dis[2000];//come表示回来的最短路,dis表示回来的最短路 int logo[2000];//标记数组 void dijkstra() { int min,k; memset(logo,0,sizeof(logo)); for(int i=1; i<=n; ++i) dis[i]=map[s][i]; dis[s]=0; logo[s]=1; for(int i=2; i<=n; ++i) { min=MAX; for(int j=1; j<=n; ++j) { if(!logo[j]&&dis[j]<min) { min=dis[j]; k=j; } } logo[k]=1; for(int j=1; j<=n; ++j) if(!logo[j]&&dis[j]>dis[k]+map[k][j]) dis[j]=dis[k]+map[k][j]; } } int main() { scanf("%d%d%d",&n,&m,&s); int sum=0; for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) map[i][j]=MAX; for(int i=0; i<m; i++) { int a,b,c; scanf("%d%d%d",&a,&b,&c); if(c<map[a][b]) map[a][b]=c; } dijkstra(); for(int i=1; i<=n; i++) come[i]=dis[i];//计算回来的最短路,然后用come记录下俩 for(int i=1; i<=n; i++)//将矩阵转置,表示从终点回来 for(int j=i+1; j<=n; j++) { int c; c=map[j][i]; map[j][i]=map[i][j]; map[i][j]=c; } dijkstra(); for(int i=1; i<=n; i++) { if(sum<come[i]+dis[i]&&i!=s) sum=come[i]+dis[i];//计算最大值 } printf("%d\n",sum); return 0; }