hdu4786 Fibonacci Tree(kruskal+并查集)

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 7965    Accepted Submission(s): 2406

Problem Description
  Coach Pang is interested in Fibonacci numbers while Uncle Yang wants him to do some research on Spanning Tree. So Coach Pang decides to solve the following problem:
  Consider a bidirectional graph G with N vertices and M edges. All edges are painted into either white or black. Can we find a Spanning Tree with some positive Fibonacci number of white edges?
(Fibonacci number is defined as 1, 2, 3, 5, 8, ... )
 
Input
  The first line of the input contains an integer T, the number of test cases.
  For each test case, the first line contains two integers N(1 <= N <= 105) and M(0 <= M <= 105).
  Then M lines follow, each contains three integers u, v (1 <= u,v <= N, u<> v) and c (0 <= c <= 1), indicating an edge between u and v with a color c (1 for white and 0 for black).
 
Output
  For each test case, output a line “Case #x: s”. x is the case number and s is either “Yes” or “No” (without quotes) representing the answer to the problem.
 
Sample Input
2
4 4
1 2 1
2 3 1
3 4 1
1 4 0
5 6
1 2 1
1 3 1
1 4 1
1 5 1
3 5 1
4 2 1
 
Sample Output
Case #1: Yes
Case #2: No

题目大意:

给定一堆权值为0或1的边,问是否能组成一棵生成树,使得生成树的边权值之和为斐波那契数列上的数

思路:

先用并查集判断是不是连通图,如果不是直接为No

边权值按从小到大的顺序排一遍,生成树求出最小值minn

边权值按从大到小的顺序排一遍,生成树求出最大值maxn

判断[minn,maxn]存不存在斐波那契数列上的数,存在Yes,不存在No(权值为1的边可以用多条权值为0的边去凑)

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 int t,n,m,ca=0;
 6 const int MAX=1e5+5;
 7 struct Edge{
 8     int from,to,val;
 9 }edge[MAX];
10 int fa[MAX],fib[MAX];
11 
12 void sol(){
13     fib[1]=fib[2]=1;
14     int bef=1,nxt=2,sum=bef+nxt;
15     while(sum<MAX){
16         fib[sum]=1;
17         bef=nxt;
18         nxt=sum;
19         sum=bef+nxt;
20     }
21 }
22 
23 int find(int x){
24     int k=x;
25     while(fa[k]!=k)k=fa[k];
26     int w=x,ww;
27     while(fa[w]!=w){
28         ww=fa[w];
29         fa[w]=k;
30         w=ww;
31     }
32     return k;
33 }
34 
35 bool cmp1(Edge x,Edge y){
36     return x.val<y.val;
37 }
38 
39 bool cmp2(Edge x,Edge y){
40     return x.val>y.val;
41 }
42 
43 int kruskal(){
44     int res=0;
45     for(int i=1;i<=n;i++)fa[i]=i;
46     for(int i=0,k=0;i<m&&k<n-1;i++,k++){
47         int fx=find(edge[i].from),fy=find(edge[i].to);
48         if(fx!=fy){
49             fa[fx]=fy;
50             res+=edge[i].val;
51         }
52     }
53     return res;
54 }
55 
56 int main(){
57     sol();
58     scanf("%d",&t);
59     while(t--){
60         scanf("%d%d",&n,&m);
61         for(int i=1;i<=n;i++)fa[i]=i;
62         for(int i=0;i<m;i++){
63             scanf("%d%d%d",&edge[i].from,&edge[i].to,&edge[i].val);
64             int fx=find(edge[i].from),fy=find(edge[i].to);
65             if(fx!=fy){
66                 fa[fx]=fy;
67             }
68         }
69         int flag=1;
70         int rt=find(1);
71         for(int i=1;i<=n;i++){
72             if(find(i)!=rt){
73                 flag=0;
74                 break;
75             }
76         }
77         if(flag==0){
78             printf("Case #%d: No
",++ca);
79             continue;
80         }
81         sort(edge,edge+m,cmp1);
82         int minn=kruskal();
83         sort(edge,edge+m,cmp2);
84         int maxn=kruskal();
85         flag=0;
86         for(int i=minn;i<=maxn;i++){
87             if(fib[i]==1){
88                 flag=1;
89                 break;
90             }
91         }
92         if(flag==1)printf("Case #%d: Yes
",++ca);
93         else printf("Case #%d: No
",++ca);
94     }
95 }
原文地址:https://www.cnblogs.com/ChangeG1824/p/11679955.html