zoukankan      html  css  js  c++  java
  • Floyd求最小环

    Floyd 可以求解图上的最小环

    这里需要注意的是无向图和有向图的求法是不一样的

    有向图 : 正常跑一遍 Floyd 再遍历所有的 dp[i][i] 即自身到自身的距离,便是所求的最小环

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 2005;
    const int INF  = 0x3f3f3f3f;
    int N, M;
    int dis[maxn][maxn];  // 记录路径长
    int path[maxn][maxn]; // 记录实际路径
    
    inline void Floyd_Warshall()
    {
        for (int i=0; i<N; ++i)
            for (int j=0; j<N; ++j)
                path[i][j] = j;
    
        for (int k=N-1; k>=0; k--) {
            for (int i=0; i<N; ++i) {
                for (int j=0; j<N; ++j) {
                    if (dis[i][j] > dis[i][k] + dis[k][j]
                     && dis[i][k] != INF && dis[k][j] != INF) {
                        dis[i][j] = dis[i][k] + dis[k][j];
                        path[i][j] = path[i][k];
                    }
                }
            }
        }
    }
    
    int main(void)
    {
        while(~scanf("%d %d", &N, &M)){
            for(int i=0; i<N; i++)
                for(int j=0; j<N; j++)
                    dis[i][j] = INF;
    
            int from, to;
            int weight;
            while(M--)
                scanf("%d %d %d", &from, &to, &weight),
                dis[from][to] = weight;
    
            Floyd_Warshall();
    
            int idx = -1;
            int MinCost = INF;
            for(int i=0; i<N; i++){
                if(dis[i][i] < MinCost){
                    MinCost = dis[i][i];
                    idx = i;
                }
            }
    
            if(idx == -1){
                puts("No solution");
                continue;
            }
    
            printf("MinCost = %d
    ", MinCost);
            int tmp = idx;
            bool flag = true;
            while(true){///输出路径
                if(flag) flag = false;
                else if(tmp == idx) break;
                printf("%d ", path[tmp][idx]);
                tmp = path[tmp][idx];
            }puts("");
        }
        return 0;
    }
    View Code

    无向图 : 参考博客 (注意:由于是无向图,所以求解出来的环都是 n ≥ 3 的,不考虑 n == 2 或者 n == 1 自环的情况)

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 2e3 + 10;
    const int INF = 0x3f3f3f3f;
    
    long long dp[maxn][maxn], G[maxn][maxn];
    long long MinCost;
    int Fa[maxn][maxn], Path[maxn], num;
    int N, M;
    
    void Floyd()
    {
        MinCost = INF;
        for(int k=1; k<=N; k++){
            for(int i=1; i<k; i++){
                for(int j=i+1; j<k; j++){
                    long long tmp = dp[i][j] + G[i][k] + G[k][j];
                    if(tmp < MinCost){
                        MinCost = tmp;
                        num = 0;
                        int p = j;
                        while(p != i){
                            Path[num++] = p;
                            p = Fa[i][p];
                        }
                        Path[num++] = i;
                        Path[num++] = k;
                    }
                }
            }
    
            for(int i=1; i<=N; i++){
                for(int j=1; j<=N; j++){
                    int tmp = dp[i][k] + dp[k][j];
                    if(dp[i][j] > tmp){
                        dp[i][j] = tmp;
                        Fa[i][j] = Fa[k][j];
                    }
                }
            }
        }
    }
    
    int main(void)
    {
        while(~scanf("%d %d", &N, &M)){
    
            for(int i=0; i<=N+1; i++)
                for(int j=0; j<=N+1; j++)
                    G[i][j] = dp[i][j]= INF,
                    Fa[i][j] = i;
    
            int from, to, weight;
            for(int i=0; i<M; i++){
                scanf("%d %d %d", &from, &to, &weight);
                weight = min((long long)weight, G[from][to]);
                G[from][to] = dp[from][to] = weight;
                G[to][from] = dp[to][from] = weight;
            }
    
    //        for(int i=1; i<=N; i++){
    //            for(int j=1; j<=N; j++){
    //                if(G[i][j] == INF) printf("%d  ", -1);
    //                else printf("%d  ", G[i][j]);
    //            }puts("");
    //        }puts("");
    
            if(MinCost == INF){
                puts("No solution");
                continue;
            }
    
           printf("%d", Path[num-1]-1);
           for(int i=num-2; i>=0; i--)
               printf(" %d", Path[i]-1);
           puts("");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    oracle10 http://localhost:5500/em打不开引发的问题
    [bbk5383] 第90集 第11章 数据库诊断 06
    [bbk5373] 第88集 第11章 数据库诊断 04
    ORA01157报错"cannot identify/lock data file"
    [bbk5361] 第86集 第11章 数据库诊断 02
    MFC里AfxGetThread()与AfxGetAPP()的区别
    VC++ 6.0 中类不见了
    MFC中的注释宏
    MFC中OnNcLButtonDown和OnNcLButtonUp的添加方法
    MFC用CWindowDC dc(GetParent())不能在标题栏画线的问题
  • 原文地址:https://www.cnblogs.com/qwertiLH/p/8723809.html
Copyright © 2011-2022 走看看