zoukankan      html  css  js  c++  java
  • HDU 4786 最小生成树变形 kruscal(13成都区域赛F)

    Fibonacci Tree

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


    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
     
    Source
     
    题意:N个顶点,M条边,每条边或为白色或为黑色( 1 or 0 ),问有没有用是斐波那契数的数目的白色边构成一棵生成树
    题解:N个顶点构成的生成树有N-1条边 ,首先判断能否能构成生成树,图是否是联通的,无法构成则输出No
    先使用所有的黑边 不断加边,看最多能使用多少条黑边使得不形成环 求得白边的使用的数量的下界
    然后再使用所有的白边,不断的加边,看最多能使用多少条白边使得不形成环,求得白边使用的数量的上界
    然后是否存在斐波那契数载这个区间

    我们等于是要证明对于所有在min和max之间的白边数我们都能够达到。

    考虑从最小的min开始,我总可以找到一条黑边,使得将它去掉在补上一条白边保持图联通。为什么呢,如果在某一个状态(设白边数为x)下,不存在一条黑边可以被白边代替,那么现在我们把所有黑边去掉,剩下x条白边,那我们知道,x一定等于max,因为若x<max,那么我们在算max的那个步骤中,先将这x条白边加入,还可以在加入max-x条白边使得不存在环,那么这与没有一条黑边可以被白边代替矛盾,所以这就证明了从min到max我都可以达到

     
      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 using namespace std;
      5 struct node
      6 {
      7     int u,v,c;
      8 } N[100005];
      9 int fib[50];
     10 int fa[100005];
     11 int t;
     12 int n,m;
     13 int coun;
     14 int find(int root)
     15 {
     16     if(root==fa[root])
     17         return root;
     18     else
     19         return fa[root]=find(fa[root]);
     20 }
     21 void unin(int a,int b)
     22 {
     23     int aa=find(a);
     24     int bb=find(b);
     25     if(aa!=bb)
     26         fa[aa]=bb;
     27 }
     28 void init()
     29 {
     30     for(int i=1; i<=n; i++)
     31         fa[i]=i;
     32 }
     33 void fi()
     34 {
     35     fib[1]=1;
     36     fib[2]=2;
     37     for(int i=3;; i++)
     38     {
     39         fib[i]=fib[i-1]+fib[i-2];
     40         if(fib[i]>100005)
     41         {
     42             coun=i;
     43             break;
     44         }
     45     }
     46 }
     47 int kruscal(int exm)
     48 {
     49     init();
     50     int k=0;
     51     for(int i=1; i<=m; i++)
     52     {
     53         if(N[i].c!=exm)
     54         {
     55             if(find(N[i].u)!=find(N[i].v))
     56             {
     57                 k++;
     58                 unin(N[i].u,N[i].v);
     59             }
     60         }
     61     }
     62     return k;
     63 }
     64 int main()
     65 {
     66     fi();
     67     while(scanf("%d",&t)!=EOF)
     68     {
     69         for(int j=1; j<=t; j++)
     70         {
     71             scanf("%d %d",&n,&m);
     72             for(int i=1; i<=m; i++)
     73             scanf("%d %d %d",&N[i].u,&N[i].v,&N[i].c);
     74             printf("Case #%d: ",j);
     75             int zha;
     76             zha=kruscal(2);//可以使用白边和黑边
     77             if(zha!=(n-1))//判环
     78             {
     79                 printf("No
    ");
     80                 continue;
     81             }
     82             int l=n-1-kruscal(1);//构成生成树的白边数量的下限
     83             int r=kruscal(0);// 构成生成树的白边数量的上限
     84             int flag=0;
     85             for(int i=1; i<coun; i++)//判断是否存在满足条件的fib
     86             {
     87                 if(fib[i]>=l&&fib[i]<=r)
     88                 {
     89                     printf("Yes
    ");
     90                     flag=1;
     91                     break;
     92 
     93                 }
     94             }
     95             if(flag==0)
     96                 printf("No
    ");
     97         }
     98     }
     99     return 0;
    100 }
  • 相关阅读:
    生成器 和 生成器 表达式
    函数的三大器
    02.python网络爬虫第二弹(http和https协议)
    python网络爬虫第三弹(<爬取get请求的页面数据>)
    线程
    网络编程
    分时操作系统 与 多道程序系统
    javascript原型深入解析2--Object和Function,先有鸡先有蛋
    javascript原型深入解析1-prototype 和原型链、js面向对象
    js模块化
  • 原文地址:https://www.cnblogs.com/hsd-/p/5703032.html
Copyright © 2011-2022 走看看