您的位置:首页 > 其它

例题11-2 苗条的生成树 UVa1395 Kruskal算法样例(基于并查集,which is almost like set)

2015-05-14 20:21 441 查看
1、题目链接

2、首先把权值排序。对于连续的边集区间[L,R],如果这些边使n个点全部连通(用并查集,逐步扩大连通集),则存在。

从小到大枚举L,从R=L开始,添加n个边,用并查集将这些边的端点合为一个并查集。

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

#define N 5000+10
#define INF 100000000
int u
, v
, w
;  //也可以struct edge
int r
, p
;
int n, m;
int find(int x)
{
return p[x] == x ? x : p[x] = find(p[x]);
}
int cmp(const int i, const int j)
{
return w[i] < w[j];
}
int Kruskal(int L)
{
int ans = -1;
int R;
for (int i = 1; i <= n; i++)//每构建一次即初始化一次并查集
p[i] = i;
for (R = L; R < m; R++)
{
int e = r[R];
int x = find(u[e]);
int y = find(v[e]);
if (x != y)  //不构成圈
{
ans = max(ans, w[e] - w[r[L]]);
p[x] = y;  //合成树,即添加边
}
}
int fa = find(1);
for (int i = 1; i <= n; i++)//判断n个点是否都连通
if (fa != find(i))
return ans=INF;
return ans;//连通就返回

}
int main()
{
while (cin >> n >> m && (n || m))
{
int ans = INF;
for (int i = 0; i < m; i++)
cin>>u[i]>>v[i]>>w[i];  //第i条边的数据
for (int i = 0; i < m; i++)
r[i] = i;
sort(r, r + m, cmp);  //注意此处排序i的意义
if (m < n - 1)cout<<"-1\n";
else
{
for (int i = 0; i < m - n + 2; i++)
ans = min(ans, Kruskal(i));
if (ans == INF)
cout<<"-1\n";
else cout<<ans;
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: