UVa 1395 苗条的生成树(Kruskal+并查集)
Posted 谦谦君子,陌上其华
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVa 1395 苗条的生成树(Kruskal+并查集)相关的知识,希望对你有一定的参考价值。
https://vjudge.net/problem/UVA-1395
题意:
给出一个n结点的图,求苗条度(最大边减最小边的值)尽量小的生成树。
思路:
主要还是克鲁斯卡尔算法,先仍是按权值排序,对于一个连续的边集区间[L,R],如果这些边使得n个点全部连通,则一定存在一个苗条度不超过W[R]-W[L]的生成树。从小到大枚举L,对于每个L,从小到大枚举R。
这道题目我一直超时,最后发现数组开小了,我一直以为数组开小了肯定会出来Runtime error的...
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 6 const int maxn = 100 + 5; 7 8 int n, m, ans; 9 int p[maxn]; 10 11 struct node 12 { 13 int u; 14 int v; 15 int w; 16 }edge[maxn*maxn]; 17 18 int find(int x) 19 { 20 return p[x] == x ? x : find(p[x]); 21 } 22 23 bool cmp(node a, node b) 24 { 25 return a.w < b.w; 26 } 27 28 29 void init() 30 { 31 for (int k = 1; k <= n; k++) p[k] = k; 32 } 33 34 void Kruskal() 35 { 36 int ok = 0; 37 sort(edge, edge + m, cmp); 38 for (int i = 0; i <= m - n + 1; i++) 39 { 40 int num = 0; 41 init(); 42 for (int j = i ; j < m; j++) 43 { 44 int x = find(edge[j].u); 45 int y = find(edge[j].v); 46 if (x != y) 47 { 48 p[x] = y; 49 num++; 50 } 51 if (num == n - 1) 52 { 53 ans = min(ans, edge[j].w - edge[i].w); 54 ok = 1; 55 break; 56 } 57 } 58 while (edge[i].w == edge[i + 1].w) i++; 59 } 60 if (!ok) printf("-1\n"); 61 else printf("%d\n", ans); 62 } 63 64 int main() 65 { 66 //freopen("D:\\txt.txt", "r", stdin); 67 while (scanf("%d%d",&n,&m)) 68 { 69 if (n == 0 && m == 0) break; 70 for (int i = 0; i<m ; i++) 71 { 72 scanf("%d%d%d", &edge[i].u, &edge[i].v , &edge[i].w); 73 } 74 ans = 1000000000; 75 Kruskal(); 76 } 77 return 0; 78 } 79
以上是关于UVa 1395 苗条的生成树(Kruskal+并查集)的主要内容,如果未能解决你的问题,请参考以下文章