UVa 1395 Slim Span【最小生成樹】

題意:給出n個節點的圖,求最大邊減最小邊儘可能小的值的生成樹ios

首先將邊排序,而後枚舉邊的區間,斷定在該區間內是否n個點連通,若是已經連通了,則構成一顆生成樹,ide

則此時的苗條度是這個區間內最小的(和kruskal同樣,若是在已經構成一顆樹的基礎上,再繼續加入邊,因爲邊都是排過序的,再加入的邊必定會更大)spa

再維護一個最小值就行了3d

 

本身寫的時候,枚舉區間沒有寫對,而後判斷1到n個點連通又寫了一個for循環code

後來看lrj的代碼:發現是這樣判斷1到n是否連通的,每次枚舉一個區間的時候,初始化cnt=n,當cnt=1時,說明已經加入了n-1條邊,構成生成樹了,那麼此時已經連通blog

 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\n");
61         else printf("%d\n",ans);
62     }
63     return 0;
64 }
View Code

 

 

 

 

 

go---go---go--排序

相關文章
相關標籤/搜索