1. 程式人生 > 其它 >POJ1734 Sightseeing trip (Floyd求最小環)

POJ1734 Sightseeing trip (Floyd求最小環)

學習了一下用Floyd求最小環,思路還是比較清晰的。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<vector>
 6 using namespace std;
 7 int a[310][310],d[310][310],pos[310][310];
 8 int n,m,ans=0x3f3f3f3f;
 9 vector<int> path;//用vector的領接表儲存最小環方案 
10
void get_path(int x,int y){ 11 if(pos[x][y]==0) return ; 12 get_path(x,pos[x][y]); 13 path.push_back(pos[x][y]); 14 get_path(pos[x][y],y); 15 } 16 17 int main(){ 18 cin>>n>>m; 19 memset(a,0x3f,sizeof(a)); 20 for(int i=1;i<=n;i++) a[i][i]=0; 21 for(int i=1
;i<=m;i++){ 22 int x,y,z; 23 cin>>x>>y>>z; 24 a[y][x]=a[x][y]=min(a[x][y],z);//選擇兩點之間最短的路徑 25 } 26 memcpy(d,a,sizeof(a));//將a全部複製到d中 27 for(int k=1;k<=n;k++){ 28 for(int i=1;i<k;i++) 29 for(int j=i+1;j<k;j++) 30 if
((long long)d[i][j]+a[j][k]+a[k][i]<ans){//更新答案 31 ans=d[i][j]+a[j][k]+a[k][i]; 32 path.clear(); 33 path.push_back(i); 34 get_path(i,j); 35 path.push_back(j); 36 path.push_back(k); 37 } 38 for(int i=1;i<=n;i++)//依據每一個k作為中轉點更新ij最短路徑 39 for(int j=1;j<=n;j++) 40 if(d[i][j]>d[i][k]+d[k][j]){ 41 d[i][j]=d[i][k]+d[k][j]; 42 pos[i][j]=k; 43 } 44 } 45 if(ans==0x3f3f3f3f){ 46 cout<<"No solution."; 47 return 0; 48 } 49 for(int i=0;i<path.size();i++) 50 cout<<path[i]<<" "; 51 }

總結一下:主要是用k作為中轉點,對於每一個k:i和j都是小於k的,先更新最小環的答案,然後用此時的k更新每個i,j的最短距離,為下一次迴圈(也就是k+1)作準備。

方程: min{d[i][j]+a[j][k]+a[k][i]} (1<=i<j<k)。

其中pos[i][j]=k,代表ij最短路間經過了k,用於get_path()。