最小环 floyd
题意:包含至少3个点的最小环思路:在i->j的一条最短路径上,只要额外加一个点k,i和j与k都有一条无向边,
就能形成路径为 i->j->k->i 的环
在floyd松弛边的过程中,不断的尝试在最短路上加多一个点 k,计算最小环的大小。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
typedef long long ll;
const int MaxnN = 100+10;
const int MaxnM = 2e5+10;
const int INF = 0x3f3f3f3f;
const ll LINF = 1e18;
ll cost[MaxnN][MaxnN], G[MaxnN][MaxnN];
ll path[MaxnN][MaxnN];
vector <int> p;
int main(void)
{
int n, m;
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= n; ++j) {
if(i == j) cost[i][j] = G[i][j] = 0;
else cost[i][j] = G[i][j] = LINF;
path[i][j] = j;
}
}
int u, v, w;
for(int i = 0; i < m; ++i) {
scanf("%d%d%d", &u, &v, &w);
cost[u][v] = cost[v][u] = G[u][v] = G[v][u] = min(G[u][v], (ll)w);
}
ll ans = LINF; // 最小环大小
for(int k = 1; k <= n; ++k) {
for(int i = 1; i < k; ++i) {
for(int j = i+1; j < k; ++j) {
if(ans > cost[i][j]+G[i][k]+G[k][j]) {
ans = cost[i][j]+G[i][k]+G[k][j];
// 存储路径
p.clear();
for(int x = i; x != j; x = path[x][j]) p.push_back(x);
p.push_back(j); p.push_back(k);
}
}
}
for(int i = 1; i <= n; ++i) {
if(i == k) continue;
for(int j = 1; j <= n; ++j) {
if(j == k || i == j) continue;
if(cost[i][j] > cost[i][k]+cost[k][j]) {
cost[i][j] = cost[i][k]+cost[k][j];
path[i][j] = path[i][k];
}
}
}
}
if(ans == LINF) puts("No solution.");
else for(int i = 0; i < p.size(); ++i) {
if(i == p.size()-1) printf("%d\n", p[i]);
else printf("%d ", p[i]);
}
return 0;
}
浙公网安备 33010602011771号