题意:一些牛要从各自的农场到某一个指定农场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 }