1. 程式人生 > >G - Slim Span (UVALive - 3887)

G - Slim Span (UVALive - 3887)

pan cst 題目 ons edge tor div 答案 init

- 題目大意

給出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;
}

  

G - Slim Span (UVALive - 3887)