zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    C语言探索之旅 | 第二部分第十一课:练习题和习作
    C语言探索之旅 | 第二部分第十课: 实战"悬挂小人"游戏答案
    C语言探索之旅 | 第二部分第九课: 实战"悬挂小人"游戏
    C语言探索之旅 | 第二部分第八课:动态分配
    C语言探索之旅 | 第二部分第七课:文件读写
    最近迫切应学的编程语言
    C语言探索之旅 | 第二部分第五课:预处理
    封装axios方法之一
    react前置路由守卫
    React Router 4.0 实现路由守卫
  • 原文地址:https://www.cnblogs.com/ChangeG1824/p/11679955.html
Copyright © 2011-2022 走看看