題意:給出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 }
go---go---go--排序