您的位置:首页 > 其它

UVa 1395 苗条的生成树(Kruskal+并查集)

2017-02-10 20:32 344 查看
https://vjudge.net/problem/UVA-1395

题意:

给出一个n结点的图,求苗条度(最大边减最小边的值)尽量小的生成树。

思路:

主要还是克鲁斯卡尔算法,先仍是按权值排序,对于一个连续的边集区间[L,R],如果这些边使得n个点全部连通,则一定存在一个苗条度不超过W[R]-W[L]的生成树。从小到大枚举L,对于每个L,从小到大枚举R。

这道题目我一直超时,最后发现数组开小了,我一直以为数组开小了肯定会出来Runtime error的...

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

const int maxn = 100 + 5;

int n, m, ans;
int p[maxn];

struct node
{
int u;
int v;
int w;
}edge[maxn*maxn];

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

bool cmp(node a, node b)
{
return a.w < b.w;
}

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

void Kruskal()
{
int ok = 0;
sort(edge, edge + m, cmp);
for (int i = 0; i <= m - n + 1; i++)
{
int num = 0;
init();
for (int j = i ; j < m; j++)
{
int x = find(edge[j].u);
int y = find(edge[j].v);
if (x != y)
{
p[x] = y;
num++;
}
if (num == n - 1)
{
ans = min(ans, edge[j].w - edge[i].w);
ok = 1;
break;
}
}
while (edge[i].w == edge[i + 1].w)   i++;
}
if (!ok)    printf("-1\n");
else         printf("%d\n", ans);
}

int main()
{
//freopen("D:\\txt.txt", "r", stdin);
while (scanf("%d%d",&n,&m))
{
if (n == 0 && m == 0)    break;
for (int i = 0; i<m ; i++)
{
scanf("%d%d%d", &edge[i].u, &edge[i].v , &edge[i].w);
}
ans = 1000000000;
Kruskal();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: