POJ 1734 Sightseeing trip (floyd求无向图最小环)

题意:给你一张无向图,让你求最小环,并且输出最小环的路径。
思路:floyd求最小环。能用floyd求最小环要满足一下几个条件:

  1. 点的个数小于500,因为floyd复杂度o(nnn)
  2. 必须是无向图,因为floyd求最短路是枚举三个点,如果是有向图,两个点即可构成一个环。

原理:最小环就是 m i n ( a [ k ] [ i ] + d [ i ] [ j ] + a [ j ] [ k ] ) min(a[k][i] + d[i][j] + a[j][k]) mina[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("");
}

猜你喜欢

转载自blog.csdn.net/weixin_44499508/article/details/106841354