HDU 1599 find the mincost route

版权声明:本人QQ 249712949 欢迎交流算法(请备注)。 https://blog.csdn.net/coord_/article/details/88956511

传送门

floyd求最小环(正环)问题。注意和HDU 1217的区别。

这个题就是套路固定这么做的,这个题和负环完全没有一点关系

是个中文题,题意就没啥可说了,这个题是个无向图,求一个至少有三个点的环,这个环在全图所有至少有三个点的环中长度最小(所谓环的长度就是绕着这个环走一圈,每条边的权值之和)。

套路就是在floyd的第一层下面,第二三层上面,再加一个两层循环,用来枚举每两个点i,j,首先保证i,j,k三个互相不等,然后,因为是在原来二三层的上面,所以这时的d[i][j]一定还没有被k优化过,也就是说目前d[i][j]中间一定没有k点,所以从ij,再找一条jk的边和一条ki的边,这就一定能保证是一条至少三个点的环路了。


#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
#include <string>
using namespace std;                             // floyd求最小环(>=3)      就当板子吧

const int MAXN = 101;
const int INF = 1e9;
int N, M;
int g[MAXN][MAXN];        // 两点间边权
int d[MAXN][MAXN];        // 两点间最短路距离
int ans;

void init()
{
	for (int i = 1; i <= N; i++)
	{
		for (int j = i; j <= N; j++)
		{
			if (i == j) g[i][j] = 0;
			else g[i][j] = g[j][i] = INF;
		}
	}
	ans = INF;
}

void floyd()
{
	for (int k = 1; k <= N; k++)
	{
		for (int i = 1; i <= N; i++)
		{
			for (int j = 1; j <= N; j++)
			{
				if (g[j][k] != INF && g[k][i] != INF && k != i && k != j && i != j)   // 防INF相加溢出,事实证明,不加会WA
				{
					ans = min(ans, d[i][j] + g[j][k] + g[k][i]);
				}
			}
		}
		for (int i = 1; i <= N; i++)
		{
			for (int j = i + 1; j <= N; j++)        // 又不是求负环,让i,j重复没有用,而且因为是无向图,i,j是对称的
			{
				if (d[i][k] != INF && d[k][j] != INF && d[i][k] + d[k][j] < d[i][j])
				{
					d[i][j] = d[j][i] = d[i][k] + d[k][j];
				}
			}
		}
	}
}

int main()
{
	int a, b, c;
	for (; ~scanf("%d%d", &N, &M);)
	{
		init();
		for (int i = 0; i < M; i++)
		{
			scanf("%d%d%d", &a, &b, &c);
			g[a][b] = g[b][a] = min(g[a][b], c);
		}

		memcpy(d, g, sizeof g);
		floyd();
		if (ans == INF) printf("It's impossible.\n");
		else printf("%d\n", ans);
	}

	return 0;
}

猜你喜欢

转载自blog.csdn.net/coord_/article/details/88956511
今日推荐