题意:一些牛要从各自的农场到某一个指定农场X,然后再回各自的农场,给出一系列单向边,求总路程最短。这题看似麻烦,因为全部从X点返回各自农场是一个X到其他所有点的最短路径问题,但是从各自点到X点貌似就是N个点各自的最短路了。但其实可以这样,从所有点到X点就是逆的X点到其他点的过程,只不过走的路径也是反的,那么其实就很简单了,正向建边用于计算从X点返回各自点,而反向建边构成一张新的图,也是计算从X点返回各点的最短路径,其实这些边本来是从各点到X,但是反向建之后就变成了X到各点了,然后就变成简单的一点到多点的最短路,就可以跑两边最短路水过去了。

dij:

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<queue>
  4 using namespace std;
  5 const int MAXM=100000;
  6 int head1[1005],next1[MAXM+5],point1[MAXM+5],val1[MAXM+5],dist1[1005],size1;
  7 bool vis1[1005];
  8 int head2[1005],next2[MAXM+5],point2[MAXM+5],val2[MAXM+5],dist2[1005],size2;
  9 bool vis2[1005];
 10 int n;
 11 void add1(int a,int b,int v){
 12     int i;
 13     for(i=head1[a];~i;i=next1[i]){
 14         if(point1[i]==b){
 15             if(val1[i]>v)val1[i]=v;
 16             return;
 17         }
 18     }
 19     point1[size1]=b;
 20     val1[size1]=v;
 21     next1[size1]=head1[a];
 22     head1[a]=size1++;
 23 }
 24 
 25 void add2(int a,int b,int v){
 26     int i;
 27     for(i=head2[b];~i;i=next2[i]){
 28         if(point2[i]==a){
 29             if(val2[i]>v)val2[i]=v;
 30             return;
 31         }
 32     }
 33     point2[size2]=a;
 34     val2[size2]=v;
 35     next2[size2]=head2[b];
 36     head2[b]=size2++;
 37 }
 38 
 39 void spfa(int s){
 40     int i;
 41     memset(dist1,-1,sizeof(dist1));
 42     dist1[s]=0;
 43     memset(vis1,0,sizeof(vis1));
 44     queue<int>q1;
 45     q1.push(s);
 46     vis1[s]=1;
 47     while(!q1.empty()){
 48         int u=q1.front();
 49         q1.pop();
 50         vis1[u]=0;
 51         for(i=head1[u];~i;i=next1[i]){
 52             int j=point1[i];
 53             if(dist1[j]==-1||dist1[j]>dist1[u]+val1[i]){
 54                 dist1[j]=dist1[u]+val1[i];
 55                 if(!vis1[j]){
 56                     q1.push(j);
 57                     vis1[j]=1;
 58                 }
 59             }
 60         }
 61     }
 62     memset(dist2,-1,sizeof(dist2));
 63     dist2[s]=0;
 64     memset(vis2,0,sizeof(vis2));
 65     queue<int>q2;
 66     q2.push(s);
 67     vis2[s]=1;
 68     while(!q2.empty()){
 69         int u=q2.front();
 70         q2.pop();
 71         vis2[u]=0;
 72         for(i=head2[u];~i;i=next2[i]){
 73             int j=point2[i];
 74             if(dist2[j]==-1||dist2[j]>dist2[u]+val2[i]){
 75                 dist2[j]=dist2[u]+val2[i];
 76                 if(!vis2[j]){
 77                     q2.push(j);
 78                     vis2[j]=1;
 79                 }
 80             }
 81         }
 82     }
 83     int ans=0;
 84     for(i=1;i<=n;i++){
 85         if(ans<dist1[i]+dist2[i])ans=dist1[i]+dist2[i];
 86     }
 87     printf("%d\n",ans);
 88 }
 89 
 90 int main(){
 91     int m,s;
 92     while(scanf("%d%d%d",&n,&m,&s)!=EOF){
 93         memset(head1,-1,sizeof(head1));
 94         size1=0;
 95         memset(head2,-1,sizeof(head2));
 96         size2=0;
 97         int i;
 98         for(i=1;i<=m;i++){
 99             int a,b,v;
100             scanf("%d%d%d",&a,&b,&v);
101             add1(a,b,v);
102             add2(a,b,v);
103         }
104         spfa(s);
105     }
106     return 0;
107 }
dij