http://acm.hdu.edu.cn/showproblem.php?pid=2066
今天复习了一下最短路和最小生成树,发现居然闹了个大笑话-----我居然一直写的是Floyd,但我自己一直以为这是Dijkstra---我居然一直把两个算法
记的是混的,还居然一直没有被别人发现,真是个大乌龙
好了,看看这道题,赤裸裸的最短路水题,首先来个Floyd的,把城市看成点,将连通的的点赋值为给定的时间,未连通的赋值为很大,这是个无向的关系
然后就是三个循环,以一个点为媒介,把每个点遍历一遍,比较找出点连通的最小值就行,稍微优化一点点就不会超时了
code
1 #include<cstdio> 2 #include<algorithm> 3 #define inf 1000000005 4 using namespace std; 5 int mp[1001][1001],q[1001]; 6 void jjc() 7 { 8 int i,j; 9 for (i=1;i<=1000;i++){ 10 for (j=1;j<=1000;j++){ 11 if (i==j) mp[i][j]=0; 12 else mp[i][j]=inf; 13 } 14 } 15 } 16 int min(int x,int y){ 17 if (x<y) return x; 18 else return y; 19 } 20 int main() 21 { 22 int t,s,d,c,i,j,k,w,mx,a,b,mn; 23 while (~scanf("%d %d %d",&t,&s,&d)) 24 { 25 jjc(); 26 mx=0;mn=inf; 27 while (t--) 28 { 29 scanf("%d %d %d",&a,&b,&c); 30 if (mp[a][b]>c) 31 mp[a][b]=mp[b][a]=c; 32 if (a>mx) mx=a; 没有给定范围,所以找范围 33 if (b>mx) mx=b; 34 if (a<mn) mn=a; 35 if (b<mn) mn=b; 36 } 37 for (k=mn;k<=mx;k++){ 38 for (i=mn;i<=mx;i++){ 39 if (mp[i][k]>=inf) continue; //稍微优化一点点 40 for (j=mn;j<=mx;j++){ 41 mp[i][j]=min(mp[i][j],mp[i][k]+mp[k][j]); 42 } 43 } 44 } 45 for (i=1;i<=s;i++) 46 scanf("%d",&q[i]); 47 int ans=inf; 48 while (d--) 49 { 50 scanf("%d",&w); 51 for (i=1;i<=s;i++) 52 { 53 if (mp[q[i]][w]<ans) 54 ans=mp[q[i]][w]; 55 } 56 } 57 printf("%d\n",ans); 58 } 59 return 0; 60 }
然后是Dijkstra的, Floyd是把任意两点的最短距离都求了出来,而Dijkstra只是求了特定的起点与所有点之间的最短路,一般情况而言,后者要快于前者,具体用哪种根据题目而定
按照距离从小到大的顺序,找出从给定起点能够到达的下一点,每找到一个这样的点,然后更新其余点之间的距离
code
1 #include<cstdio> 2 #define inf 100000005 3 using namespace std; 4 int map[1001][1001],vis[1001],dis[1001]; 5 int st[1001],sr[1001]; 6 int mn,mx; 7 int min(int x,int y) 8 { 9 if (x<y) return x; 10 else return y; 11 } 12 void jjc() 13 { 14 int i,j; 15 for (i=1;i<=1000;i++){ 16 for (j=1;j<=1000;j++){ 17 if (i==j) map[i][j]=0; 18 else map[i][j]=inf; 19 } 20 } 21 } 22 void dijkstra(int x) 23 { 24 int i,pos,j,q; 25 for (i=mn;i<=mx;i++) 26 { 27 dis[i]=map[x][i]; 28 vis[i]=0; 29 } 30 vis[x]=1; 31 for (i=mn;i<=mx;i++) 32 { 33 q=inf;pos=x; 34 for (j=mn;j<=mx;j++) 35 if (!vis[j]&&dis[j]<q) 36 { 37 pos=j; 38 q=dis[j]; 39 } 40 vis[pos]=1; 41 for (j=mn;j<=mx;j++) 42 dis[j]=min(dis[j],dis[pos]+map[pos][j]); 43 } 44 } 45 int main() 46 { 47 int t,s,d,a,b,c,i,j; 48 while (~scanf("%d %d %d",&t,&s,&d)) 49 { 50 jjc(); 51 mx=0,mn=inf; 52 while (t--) 53 { 54 scanf("%d %d %d",&a,&b,&c); 55 if (map[a][b]>c) 56 map[a][b]=map[b][a]=c; 57 if (a>mx) mx=a; 58 if (b>mx) mx=b; 59 if (a<mn) mn=a; 60 if (b<mn) mn=b; 61 } 62 for (i=1;i<=s;i++) 63 scanf("%d",&st[i]); 64 for (i=1;i<=d;i++) 65 scanf("%d",&sr[i]); 66 int ans=inf; 67 for (i=1;i<=s;i++) 68 { 69 dijkstra(st[i]); 70 for (j=1;j<=d;j++) 71 if (dis[sr[j]]<ans) 72 ans=dis[sr[j]]; 73 } 74 printf("%d\n",ans); 75 } 76 return 0; 77 }
队列储存,广搜版的spfa
code
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #define inf 0x3fffffff 5 using namespace std; 6 int map[1001][1001],vis[1001],dis[1001]; 7 int st[1001],sr[1001]; 8 int mn,mx,s,d; 9 void jjc() 10 { 11 int i,j; 12 for (i=1;i<=1000;i++){ 13 for (j=1;j<=1000;j++){ 14 if (i==j) map[i][j]=0; 15 else map[i][j]=inf; 16 } 17 } 18 } 19 int spfa() 20 { 21 int num,i; 22 memset(vis,0,sizeof(vis)); 23 for (i=mn;i<=mx;i++) 24 dis[i]=inf; 25 queue<int> q; 26 for (i=1;i<=s;i++) 27 { 28 dis[st[i]]=0; 29 q.push(st[i]); 30 } 31 while(!q.empty()) 32 { 33 num=q.front(); 34 q.pop(); 35 vis[num]=0; 36 for (i=mn;i<=mx;i++) 37 { 38 if (dis[i]>dis[num]+map[num][i]) 39 { 40 dis[i]=dis[num]+map[num][i]; 41 if (vis[i]==0) 42 { 43 vis[i]=1; 44 q.push(i); 45 } 46 } 47 } 48 } 49 int p=inf; 50 for (i=1;i<=d;i++) 51 { 52 if (p>dis[sr[i]]) p=dis[sr[i]]; 53 } 54 return p; 55 } 56 int main() 57 { 58 int t,a,b,c,i,j; 59 while (~scanf("%d %d %d",&t,&s,&d)) 60 { 61 jjc(); 62 mx=0,mn=inf; 63 while (t--) 64 { 65 scanf("%d %d %d",&a,&b,&c); 66 if (map[a][b]>c) 67 map[a][b]=map[b][a]=c; 68 if (a>mx) mx=a; 69 if (b>mx) mx=b; 70 if (a<mn) mn=a; 71 if (b<mn) mn=b; 72 } 73 for (i=1;i<=s;i++) 74 scanf("%d",&st[i]); 75 for (i=1;i<=d;i++) 76 scanf("%d",&sr[i]); 77 int ans=spfa(); 78 printf("%d\n",ans); 79 } 80 return 0; 81 }