- 题目大意
给出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
");
else
printf("%d
", tmp);
}
return 0;
}