poj 3522【Slim Span】

题意:给你一个无向图,没有重边,没有自环,要你求该图中一颗生成树,但是这个生成树的最大边与最小边的差值要最小。

如果固定一个最小边,求得最小生成树后,最大边也就知道了,其实这个也意味着在固定最小边的情况下最小生成树的最大边是固定的,可是为什么我们一定要求最小生成树呢,因为其他的生成树的最大边与最小边的差值要大于等于最小生成树的大小边之差,这个的原因大家可以自己仔细想想最小生成树的性质和次小生成树的求法(枚举每条最小生成树上的边,不要此条边求得的生成树,选最小一个就是了,这个就意味着次小生成树里面肯定有一条边要比最小生成树的大,其它的相同)。这样说来的话,我们只需将边排好序后,枚举每条边,并用Krustral求得最小生成树就可以了……(参考:http://blog.csdn.net/sdj222555/article/details/7698978

 

View Code
 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <cstdio>
 5 using namespace std;
 6 
 7 struct node
 8 {
 9     int x,y;
10     int w;
11 }edge[10000];
12 int father[110];
13 int n,m;
14 
15 bool cmp(const node& a,const node& b)
16 {
17     return a.w < b.w;
18 }
19 
20 int find(int x)
21 {
22     return father[x] = (x == father[x]?x:(find(father[x])));
23 }
24 
25 int Krustral(int x)
26 {
27     int num = 0;
28     int ans = -1;
29     for(int i = x;i < m;i ++)
30     {
31         int fa = find(edge[i].x);
32         int fb = find(edge[i].y);
33         if(fa == fb)
34         {
35             continue;
36         }
37         father[fa] = fb;
38         num ++;
39         if(num == n-1)
40         {
41             ans = edge[i].w;
42             break;
43         }
44     }
45     return ans;
46 }
47 
48 int main()
49 {
50     //freopen("in.txt","r",stdin);
51    // freopen("out.txt","w",stdout);
52     while(cin >> n >> m,n||m)
53     {
54         for(int i = 0;i < m;i ++)
55         {
56             cin >> edge[i].x >> edge[i].y >> edge[i].w;
57         }
58         if(m < n - 1)
59         {
60             cout << "-1" << endl;
61             continue;
62         }
63         sort(edge,edge+m,cmp);
64         int minn = -1;
65         for(int i = 0;i <= m - n + 1;i ++)
66         {
67             for(int j = 1;j <= n;j ++)
68             {
69                 father[j] = j;
70             }
71             int ans = Krustral(i);
72             if(ans != -1)
73             {
74                 if(minn == -1 || minn > ans - edge[i].w)
75                 {
76                     minn = ans - edge[i].w;
77                 }
78             }
79         }
80         cout << minn << endl;
81     }
82     return 0;
83 }

转载于:https://www.cnblogs.com/Shirlies/archive/2012/09/02/2667448.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值