UVa 1395 Slim Span【最小生成树】

题意:给出n个节点的图,求最大边减最小边尽量小的值的生成树

首先将边排序,然后枚举边的区间,判定在该区间内是否n个点连通,如果已经连通了,则构成一颗生成树,

则此时的苗条度是这个区间内最小的(和kruskal一样,如果在已经构成一颗树的基础上,再继续加入边,由于边都是排过序的,再加入的边一定会更大)

再维护一个最小值就好了

自己写的时候,枚举区间没有写对,然后判断1到n个点连通又写了一个for循环

后来看lrj的代码:发现是这样判断1到n是否连通的,每次枚举一个区间的时候,初始化cnt=n,当cnt=1时,说明已经加入了n-1条边,构成生成树了,那么此时已经连通

 1 #include<iostream>  
 2 #include<cstdio>  
 3 #include<cstring> 
 4 #include <cmath> 
 5 #include<stack>
 6 #include<vector>
 7 #include<map> 
 8 #include<set>
 9 #include<queue> 
10 #include<algorithm>  
11 #define mod=1e9+7;
12 using namespace std;
13 
14 typedef long long LL;
15 const int INF = 0x7fffffff;
16 const int maxn=10005;
17 int p[maxn];
18 
19 struct edge{
20     int v,u,w;
21     bool operator <(const edge& rhs) const{
22      return w<rhs.w;}
23 };
24 
25 
26 
27 int find(int x){return p[x]==x? x:p[x]=find(p[x]);}
28 
29 int main(){
30     int n,m,i,j,ans;
31     while(scanf("%d %d",&n,&m)!=EOF&&n){
32         vector<edge> e;
33         edge ee;
34         for(i=0;i<m;i++){
35             scanf("%d %d %d",&ee.v,&ee.u,&ee.w);
36             e.push_back(ee);
37         }
38         
39         sort(e.begin(),e.end());
40         
41         int l,r;
42         ans=INF;
43         for(l=0;l<m;l++){            
44             int cnt=n;
45             for(i=0;i<=n;i++) p[i]=i;
46             for(r=l;r<m;r++){
47                 int x=find(e[r].v);
48                 int y=find(e[r].u);
49                 if(x!=y) {
50                     p[x]=y;
51                     cnt--;
52                     if(cnt==1) {
53                     ans=min(ans,e[r].w-e[l].w);
54                     break;
55                     }
56                 }
57             }
58         }
59         
60         if(ans==INF) printf("-1
");
61         else printf("%d
",ans);
62     }
63     return 0;
64 }
View Code

go---go---go--

原文地址:https://www.cnblogs.com/wuyuewoniu/p/4391300.html