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\n", 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

 

posted @ 2018-04-05 18:49  qwerity  阅读(187)  评论(0编辑  收藏  举报