LOJ Sightseeing 【floyd最小环】

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 }
View Code

fighting fighting fighting

猜你喜欢

转载自www.cnblogs.com/Frank-King/p/9751274.html