题意:给你一张无向图,让你求最小环,并且输出最小环的路径。
思路:floyd求最小环。能用floyd求最小环要满足一下几个条件:
- 点的个数小于500,因为floyd复杂度o(nnn)
- 必须是无向图,因为floyd求最短路是枚举三个点,如果是有向图,两个点即可构成一个环。
原理:最小环就是 m i n ( a [ k ] [ i ] + d [ i ] [ j ] + a [ j ] [ k ] ) min(a[k][i] + d[i][j] + a[j][k]) min(a[k][i]+d[i][j]+a[j][k]),可以结合 f l o y d floyd floyd最短路思想理解。
#include <bits/stdc++.h>
#define pb push_back
#define ll long long
using namespace std;
int a[105][105],d[105][105],pos[105][105];
vector<int>ans;
void get_path(int i, int j)
{
if(pos[i][j] == 0)return ;
get_path(i, pos[i][j]);
ans.pb(pos[i][j]);
get_path(pos[i][j], j);
}
int main()
{
int n,m;
scanf("%d%d", &n, &m);
memset(a, 0x3f, sizeof(a));
for(int i = 1; i <= n; i++)a[i][i] = 0;
for(int i = 1; i <= m; i++)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
a[u][v] = a[v][u] = min(a[u][v] , w);
}
memcpy(d, a, sizeof(a));
int tot = 0x3f3f3f3f;
for(int k = 1; k <= n; k++)
{
for(int i = 1; i < k; i++)
for(int j = i + 1; j < k; j++)
{
if(1ll*a[k][i] + d[i][j] + a[j][k] < tot)
{
tot = a[k][i] + d[i][j] + a[j][k];
ans.clear();
ans.pb(i);
get_path(i,j);
ans.pb(j);
ans.pb(k);
}
}
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
if(1ll*d[i][k] + d[k][j] < d[i][j])
{
d[i][j] = d[i][k] + d[k][j];
pos[i][j] = k;
}
}
if(tot == 0x3f3f3f3f)printf("No solution.");
else {
for(int i = 0; i < ans.size(); i++)
printf("%d ",ans[i]);
}
puts("");
}