hdu1598 求满足最大权值最小权值差最小的生成树

/*题意:已知一张图,给定起点终点,求出包含起点和终点的生成树:
使得生成树的最大边权与最小边权之差最小,并输出其值。若不连通,输出-1*/

/*
思路:先对边按权值排序。然后从最小的边开始枚举至最大边,然后枚举比当前边大的所有边,
直到出现满足条件的生成树为止,此时更新ans。
*/

#include 
#include 
#include 
#include 
#define N 205

using namespace std;

const int inf = 0x3f3f3f3f;

typedef struct note {
	int u; int v; int w;
}edge;

edge e[5 * N];

int f[N];
int n, m;

int cmp(edge a, edge b)
{
	return a.w < b.w;
}

void init()
{
	for (int k = 1; k <= n; k++)
		f[k] = k;
}

int find(int x)
{
	return x == f[x] ? x : f[x] = find(f[x]);
}

int merge(int x, int y)
{
	int t1, t2;
	t1 = find(x); t2 = find(y);
	if (t1 != t2)
	{
		f[t2] = t1;
		return 1;
	}
	return 0;
}

int main()
{
	while (scanf("%d%d", &n, &m) != EOF)
	{
		int ans;
		for (int i = 1; i <= m; i++)
			scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w);
		sort(e + 1, e + m + 1, cmp);
		int T;
		scanf("%d", &T);
		while (T--)
		{
			int start, endd;
			scanf("%d%d", &start, &endd);
			ans = inf;
			for (int i = 1; i <= m; i++)
			{
				init();//每次枚举最小边时,都要初始化集合
				for (int j = i; j <= m; j++)//从i开始枚举,方便输出仅有一条边(ans为0)的情况
				{
					merge(e[j].u, e[j].v);
					if (find(start) == find(endd))
					{
						ans = min(ans, e[j].w - e[i].w);
						break;//一旦找到符合条件的生成树,此时舒适度一定是当前最小的,直接跳出循环
					}
				}
			}
			if (ans == inf) ans = -1;//图不连通
			printf("%d\n", ans);
		}
	}
	return 0;
}

你可能感兴趣的:(最小生成树,并查集)