floyd求最小环

hdu1599 floyd求最小环

其实floyd求最小环就相当于找出一个一条只包括1到k-1中节点的路径,然后把这个路径与k这个节点相连。这样是正确的原因是,最小环中一定有一个最大节点k,当最外层节点是k时,我们一定会枚举到k两端的两个节点,这样就统计出了答案。至于为什么不能直接用最短路径,而是要用前k-1个节点跑出来的最短路径,是因为不知道最短路径有没有经过k。

反正这个算法是对的就对了。

#include <cstdio>
#include <algorithm>
using namespace std;

const int maxn=105, INF=1e9;
int n, m, minm, dis[maxn][maxn], ori[maxn][maxn];

int main(){
    while (~scanf("%d%d", &n, &m)){
        for (int i=1; i<=n; ++i)
            for (int j=1; j<=n; ++j){
                dis[i][j]=dis[j][i]=INF;
                ori[i][j]=ori[j][i]=INF;
            }
        int x, y, v; minm=INF;
        for (int i=1; i<=m; ++i){
            scanf("%d%d%d", &x, &y, &v);
            ori[x][y]=ori[y][x]=min(ori[x][y], v);
            dis[x][y]=dis[y][x]=min(ori[x][y], v);
        }
        for (int k=1; k<=n; ++k){
            for (int i=1; i<=n; ++i)
                for (int j=1; j<=n; ++j)
                //三点都要不相同。ij不一定,但是相同的点ori一定是INF。
                //所以只需要判断i!=j。
                if (i!=j&&dis[i][j]!=INF&&ori[j][k]!=INF
                        &&ori[k][i]!=INF)
                    minm=min(minm, dis[i][j]+ori[j][k]+ori[k][i]);
            for (int i=1; i<=n; ++i)
                for (int j=1; j<=n; ++j)
                    dis[i][j]=min(dis[i][j], dis[i][k]+dis[k][j]);
        }
        if (minm==INF) printf("It's impossible.
");
        else printf("%d
", minm);
    }
}
原文地址:https://www.cnblogs.com/MyNameIsPc/p/7905673.html