hdu4786 Fibonacci Tree[最小生成树]【结论题】

一道结论题:如果最小生成树和最大生成树之间存在fib数,成立。不存在或者不连通则不成立。由于是01图,所以这个区间内的任何生成树都存在

证明:数学归纳?如果一棵树没有办法再用非树边0边替代1边了,那他就是最小生成树。如果一棵生成树大于最小生成树,那么他显然存在可以被替换的1边,否则会与最小矛盾。最大生成树存在(与最小生成树相等时显然结论成立),那么他一定可以有可以替换的边,所以所有区间内的生成树都存在。

吐槽:我一开始以为要依据fib的性质合并块。。研究好久。。冏。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<queue>
 7 #define dbg(x) cerr << #x << " = " << x <<endl
 8 #define dbg2(x,y) cerr<< #x <<" = "<< x <<"  "<< #y <<" = "<< y <<endl
 9 using namespace std;
10 typedef long long ll;
11 typedef double db;
12 typedef pair<int,int> pii;
13 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
14 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
15 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;}
16 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;}
17 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
18 template<typename T>inline T read(T&x){
19     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
20     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
21 }
22 const int N=1e5+7;
23 struct thxorz{int u,v,w;}e[N];
24 struct stothx{int nxt,to;}G[N<<1];
25 int Head[N],tot;
26 inline void Addedge(int x,int y){
27     G[++tot].to=y,G[tot].nxt=Head[x],Head[x]=tot;
28     G[++tot].to=x,G[tot].nxt=Head[y],Head[y]=tot;
29 }
30 int vis[N];
31 void dfs(int x){
32     vis[x]=1;
33     for(register int j=Head[x];j;j=G[j].nxt)if(!vis[G[j].to])dfs(G[j].to);
34 }
35 int T,n,m,minst,maxst,flag;
36 struct dsu{
37     int anc[N];
38     inline void Clear(){for(register int i=1;i<=n;++i)anc[i]=i;}
39     inline int Find(int x){return anc[x]==x?x:anc[x]=Find(anc[x]);}
40 }S;
41 int fib[]={1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368,75025};//24
42 
43 int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
44     read(T);for(register int testcase=1;testcase<=T;++testcase){
45         read(n),read(m);minst=maxst=flag=0;
46         memset(Head,0,sizeof Head);tot=0;
47         for(register int i=1;i<=m;++i)read(e[i].u),read(e[i].v),read(e[i].w),Addedge(e[i].u,e[i].v);
48         memset(vis,0,sizeof vis);dfs(1);
49         for(register int i=1;i<=n;++i)if(!vis[i]){flag=1;break;}
50         if(flag){printf("Case #%d: No\n",testcase);continue;}
51         S.Clear();
52         for(register int i=1;i<=m;++i)if(!e[i].w)if(S.Find(e[i].u)^S.Find(e[i].v))
53             S.anc[S.anc[e[i].u]]=S.anc[e[i].v];
54         for(register int i=1;i<=m;++i)if(e[i].w)if(S.Find(e[i].u)^S.Find(e[i].v))
55             S.anc[S.anc[e[i].u]]=S.anc[e[i].v],++minst;
56         S.Clear();
57         for(register int i=1;i<=m;++i)if(e[i].w)if(S.Find(e[i].u)^S.Find(e[i].v))
58             S.anc[S.anc[e[i].u]]=S.anc[e[i].v],++maxst;
59         for(register int i=1;i<=m;++i)if(!e[i].w)if(S.Find(e[i].u)^S.Find(e[i].v))
60             S.anc[S.anc[e[i].u]]=S.anc[e[i].v];
61         int x=lower_bound(fib+1,fib+24,minst)-fib;
62         if(maxst>=fib[x])printf("Case #%d: Yes\n",testcase);
63         else printf("Case #%d: No\n",testcase);
64     }
65     return 0;
66 }
View Code

总结:做生成树问题没有什么其他方法,所以还是最好多往MST上去想。。

posted @ 2019-10-17 17:50  Ametsuji_akiya  阅读(139)  评论(0编辑  收藏  举报