胡扯扩展Floyd算法

Problem

给定一个有向图,求一个至少经过2个点的最小环。

Solution

Floyd算法的代码如下

1
2
3
4
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
chkmn(sp[i][j],sp[i][k]+sp[k][j]);

外层循环执行完k==Xk==X的循环,表示两两节点之间只走1...X1...X的最短路已经被求出。 考虑一个环,上面一定有一个编号最大的点 以上图为例,在第66次循环之前,所有点对经过1...651...65的最短路已经求出,由于最短路中一定没有点6666,所以可以放心地尝试把6666号点加进去而不必担心出现重边。 于是算法就出来了:额外记录原图的边edge[][]edge[][],在sp[][]sp[][]上求最短路。第kk次循环之前,枚举每对点i,j<ki,j< k,把sp[i][j]sp[i][j]连到edge[j][k]edge[j][k]edge[k][i]edge[k][i]上,用这个环的大小来更新答案。

Code

1
2
3
4
5
6
7
8
9
for(int k=1;k<=n;k++)
{
for(int i=1;i<k;i++)
for(int j=i+1;j<k;j++)
chkmn(res,sp[i][j]+dist[j][k]+dist[k][i]);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
chkmn(sp[i][j],sp[i][k]+sp[k][j]);
}