LOJ Sightseeing
题面见链接。。。
题解:
用 floyd 我也不知道怎么想到的。。。
floyd 外层 k 循环时, dis[i][j] 保存着编号不超过 k-1 的节点从 i 到 j 的长度。
所以 ans=min (dis[i][j] + a[j][k] + a[k][i] )
中间通过 path 数组存 i 到 j 的当前最短路径的中间路径。
若 dis 被更新,则 path 同时也更新。。
详情请见代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=305; 4 int n,m,a[N][N],ans,dis[N][N],path[N][N],q[N],cnt=0; 5 inline void print(int x,int y) 6 { 7 if (!path[x][y]) return; 8 print(x,path[x][y]); 9 q[++cnt]=path[x][y]; 10 print(path[x][y],y); 11 } 12 inline void doing() 13 { 14 for (int k=1; k<=n; ++k) 15 { 16 for (int i=1; i<k; ++i) 17 for (int j=i+1; j<k; ++j) 18 { 19 if ((long long)dis[i][j]+a[j][k]+a[k][i]<ans) 20 { 21 ans=dis[i][j]+a[j][k]+a[k][i]; 22 cnt=0; q[++cnt]=i; 23 print(i,j); 24 q[++cnt]=j; q[++cnt]=k; 25 } 26 } 27 for (int i=1; i<=n; ++i) 28 { 29 if (i==k) continue; 30 for (int j=1; j<=n; ++j) 31 { 32 if (j==i || j==k) continue; 33 if (dis[i][j]>dis[i][k]+dis[k][j]) 34 { 35 dis[i][j]=dis[i][k]+dis[k][j]; 36 path[i][j]=k; 37 } 38 } 39 } 40 } 41 } 42 int main() 43 { 44 scanf("%d%d",&n,&m); 45 memset(a,0x3f,sizeof a); 46 ans=0x3f3f3f3f; 47 for (int i=1; i<=m; ++i) 48 { 49 int x,y,z; 50 scanf("%d%d%d",&x,&y,&z); 51 a[x][y]=a[y][x]=min(a[x][y],z); 52 } 53 memcpy(dis,a,sizeof(a)); 54 doing(); 55 if (ans==0x3f3f3f3f) printf("No solution."); 56 else for (int i=1; i<=cnt; ++i) printf("%d ",q[i]); 57 return 0; 58 }
fighting fighting fighting