POJ 3522 最大边与最小边差值最小的生成树

题目链接: http://poj.org/problem?id=3522

题目大意:

  给定一个简单图,n个点,m条边( 1<=n<=100,0 ≤ m ≤ n(n − 1)/2 ),要求一颗生成树,使得其最大边与最小边的差值是所有生成树中最小的,输出最小的那个差值。

分析:

  类似于kruskal算法求最小生成树,将所有边按权值大小排升序,e1,e2,e3,...em。

  枚举每条边ei,对ei,ei+1,ei+2,ei+3...进行求生成树,不断更新差值得到最优值,具体见代码,复杂度不大会算。

注意:

  开始我认为自己是水过的,因为我看到n是100的最大值,然后考虑到边是10000的最大值,便有了10000*10000的复杂度, 后来仔细想想,题目给的边数m<5000,那么自然有5000*5000不会超时。

  另外,我开始有个想法是: 每枚举边ei,做完一遍生成树后,删除边ei,维护相关信息,然后再做生成树,这样就是从ei+1开始了,复杂的会大大降低,但是我还是想不出来如何删边且维护相关信息。

代码:

poj3522
 1 /*3522    Accepted    320K    63MS    C++    1681B    2012-04-20 11:09:28*/
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <iostream>
 6 #include <algorithm>
 7 #include <vector>
 8 using namespace std;
 9 
10 #define mpair make_pair
11 #define pii pair<int,int>
12 #define MM(a,b) memset(a,b,sizeof(a));
13 typedef long long lld;
14 typedef unsigned long long u64;
15 template<class T> bool up_max(T& a,const T& b){return b>a? a=b,1 : 0;}
16 template<class T> bool up_min(T& a,const T& b){return b<a? a=b,1 : 0;}
17 #define maxn
18 
19 int n,m;
20 struct Edge{
21     int u,v,w;
22     void read(){
23         scanf("%d%d%d", &u, &v, &w);
24     }
25     bool operator<(Edge b)const{
26         return w<b.w;
27     }
28 } edge[10050];
29 
30 const int inf= 200000000;
31 int fa[110];
32 int find(int x){
33     if( x==fa[x] ) return x;
34     else return fa[x]= find( fa[x] );
35 }
36 int solve(){
37     int ans= inf;
38     for(int k=1;k<=m;++k){
39         for(int i=1;i<=n;++i) fa[i]= i;
40         int mmin= inf, mmax= -inf;
41         int cnt= 0;
42 
43         for(int i=k;i<=m;++i){
44             int x= edge[i].u, y= edge[i].v;
45             int fx= find(x), fy= find(y);
46             if( fx!=fy ){
47                 fa[fy]= fx;
48                 up_min( mmin, edge[i].w );
49                 up_max( mmax, edge[i].w );
50                 if( ++cnt == n-1 ) break;
51                 if( mmax-mmin >= ans ) break; ///
52             }
53         }
54         if( cnt == n-1 ) up_min( ans, mmax-mmin );
55     }
56     return ans;
57 }
58 
59 int main()
60 {
61     while( cin>>n>>m, (n+m) ){
62         for(int i=1;i<=m;++i)
63             edge[i].read();
64         sort( edge+1, edge+1+m );
65 
66         int ans= solve();
67         if( ans!=inf ) cout<< ans <<endl;
68         else puts("-1");
69     }
70 }
一毛原创作品,转载请注明出处。
原文地址:https://www.cnblogs.com/yimao/p/2459060.html