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; }
无向图 : 参考博客 (注意:由于是无向图,所以求解出来的环都是 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; }