POJ3268 Silver Cow Party

题目链接:https://vjudge.net/problem/POJ-3268

解题思路:

  各牛从 $X$ 回家的最短路很容易求,用 $Dijkstra$ 求 $X$ 到各点的单源最短路即可。难点在于求各牛从家到 $X$ 点的最短路,因为路是单向的,所以往返的最短路未必相等。在这点有一个很巧妙的解决思路:把已知的各单向路倒置,权值不变,再用一次 $Dijkstra$,此时的X到各点的单源最短路其实就是各点到X的最短路。

AC代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 using namespace std;
 4 int len[1005][1005],dlen[1005][1005];
 5 int vis[1005],d[1005],dvis[1005],dd[1005];
 6 const int INF=1e8;
 7 int main()
 8 {
 9     int N,M,X;
10     scanf("%d%d%d",&N,&M,&X);
11     for(int i=1;i<=N;i++){
12         for(int j=1;j<=N;j++){
13             if(i==j)    len[i][j]=len[j][i]=dlen[i][j]=dlen[j][i]=0;
14             else    len[i][j]=len[j][i]=dlen[i][j]=dlen[j][i]=INF;
15         }
16         d[i]=dd[i]=INF;
17     }
18     d[X]=dd[X]=0;
19     while(M--){
20         int a,b,t;
21         scanf("%d%d%d",&a,&b,&t);
22         len[a][b]=dlen[b][a]=t;
23     }
24     while(1){
25         int v=-1;
26         for(int u=1;u<=N;u++){
27             if(!vis[u] && (v==-1||d[u]<d[v]))   v=u;
28         }
29         if(v==-1)   break;
30         vis[v]=1;
31         for(int u=1;u<=N;u++)
32             d[u]=min(d[u],d[v]+len[v][u]);
33     }
34     while(1){
35         int v=-1;
36         for(int u=1;u<=N;u++){
37             if(!dvis[u] && (v==-1||dd[u]<dd[v]))    v=u;
38         }
39         if(v==-1)   break;
40         dvis[v]=1;
41         for(int u=1;u<=N;u++)
42             dd[u]=min(dd[u],dd[v]+dlen[v][u]);
43     }
44     int ans=0;
45     for(int i=1;i<=N;i++){
46         if(dd[i]+d[i]>ans)
47             ans=dd[i]+d[i];
48     }
49     printf("%d\n",ans);
50 
51     return 0;
52 }

 

posted @ 2017-07-16 16:56  Blogggggg  阅读(344)  评论(0编辑  收藏  举报