G - Slim Span (UVALive - 3887)

- 题目大意

    给出N个点,M条边,求出一棵包含N个点的树,且树的最大权值-最小权值达到最小。

- 解题思路

    我们可以先把边排序,枚举最小的,然后利用kruskal加边,当图第一次连通的时候当前的边就是尽可能小的最大边,更新答案即可。

- 代码

#include<algorithm>
#include<cstdio>
#include<cmath>
using namespace std;
const int MAX = 1e6;
const int INF = 0x3f3f3f;
int fa[MAX];
int sum,sum1,tmp;
void init(int n)
{
	for (int i = 1; i <= n; i++)
	{
		fa[i] = i;
	}
}

struct Edge {
	int u, v, w;
	bool operator<(const Edge &rhs)const {
		return w < rhs.w;
	}
}e[MAX];

int find(int x)
{
	if (x == fa[x])
		return x;
	else
		return fa[x] = find(fa[x]);
}

bool Union(int x, int y)
{
	int fx = find(x), fy = find(y);
	if (fx == fy)
		return false;
	fa[fx] = fy;
	return true;
}

void kruskal(int n,int m)
{
	sort(e, e + m);
	for (int j = 0; j < m; j++)
	{
		init(n);
		sum = 0;
		int minn = INF, maxn = -INF;
		for (int i = j; i < m; i++)
		{
			int u = e[i].u, v = e[i].v, w = e[i].w;
			if (Union(u, v))
			{
				sum ++;
				maxn = max(maxn, w);
				minn = min(minn, w);

			if (sum == n - 1)
			{
				tmp = min(tmp, (maxn - minn));
				break;
			}
			}
		}
	}
}

int main()
{
	int n, m;
	while (scanf("%d%d", &n, &m))
	{
		if (n == 0 && m == 0)
			break;
        tmp=INF;
		for (int i = 0; i<m; i++)
		{
			scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w);
		}
		kruskal(n,m);
		if (tmp==INF)
			printf("-1\n");
		else
			printf("%d\n", tmp);
	}
	return 0;
}

  

posted @ 2018-02-15 13:38  Alpacaddhh  阅读(132)  评论(0编辑  收藏  举报