给定一张无向图,求图中一个至少包含3个点的环,环上的节点不重复,并且环上的边的长度之和最小。
该问题称为无向图的最小环问题。
你需要输出最小环的方案,若最小环不唯一,输出任意一个均可。
输入格式
第一行包含两个整数N和M,表示无向图有N个点,M条边。
接下来M行,每行包含三个整数u,v,l,表示点u和点v之间有一条边,边长为l。
输出格式
输出占一行,包含最小环的所有节点(按顺序输出),如果不存在则输出’No solution.’。
数据范围
1≤N≤1001≤N≤100,
1≤M≤100001≤M≤10000,
1≤l<5001≤l<500
输入样例:
5 7
1 4 1
1 3 300
3 1 10
1 2 16
2 3 100
2 5 15
5 3 20
输出样例:
1 3 5 2
注意:floyd算法中k是I和j中间的一个点,这里采用变形,注意题目是让按照顺序输出,卡了好久
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 110, INF = 0x3f3f3f3f;
int n, m;
int d[N][N], g[N][N];
int pos[N][N];
int path[N], cnt;
void get_path(int i, int j){
if (pos[i][j] == 0) return;
int k = pos[i][j];
get_path(i, k);
path[cnt ++] = k;
get_path(k, j);
}
int main(){
cin >> n >> m;
memset(g, 0x3f, sizeof g);
for (int i = 1; i <= n; i ++) g[i][i] = 0;
while(m --){
int a, b, c;
cin >> a >> b >> c;
g[a][b] = g[b][a] = min(c, g[a][b]);
}
memcpy(d, g, sizeof d);
int res = INF;
for (int k = 1; k <= n; k ++){
for (int i = 1; i < k; i ++)
for (int j = i + 1;j < k; j ++)
if ((long long)d[i][j] + g[i][k] + g[k][j] < res){
res = d[i][j] + g[i][k] + g[k][j];
cnt = 0;
path[cnt ++] = i;
path[cnt ++] = k;
get_path(i, j);
path[cnt ++] = j;
}
for (int i = 1; i <= n; i ++)
for (int j = 1; j <= n; j ++)
if (d[i][j] > d[i][k] + d[k][j]){
d[i][j] = d[i][k] + d[k][j];
pos[i][j] = k;
}
}
if (res == INF) puts("No solution.");
else{
for (int i = 0; i < cnt; i ++) cout << path[i] << " ";
cout << endl;
}
return 0;
}