HDU 4786 Fibonacci Tree(生成树,YY乱搞)

http://acm.hdu.edu.cn/showproblem.php?pid=4786

Fibonacci Tree
Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1733    Accepted Submission(s): 543

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

2013 Asia Chengdu Regional Contest

题意:

给出一个无向图,每条边都已染色(黑/白),问是否存在生成树,该生成树的白色边的数量是正的fibonacci数。

分析:

所给数据中黑边为0,白边为1,那么生成树的白边数量即为生成树的权和。

然后YY了一个做法:求其最小和最大生成树,如果在这个范围内存在fibonacci数则存在。

靠谱的证明方法一直没想出来,这里随便解释下:

对于任意一颗非最大生成树,一定可以取一条白边换一条黑边使其仍然是一颗树。

/*
 *
 * Author : fcbruce
 *
 * Time : Mon 06 Oct 2014 01:06:30 PM CST
 *
 */
#include <cstdio>
#include <iostream>
#include <sstream>
#include <cstdlib>
#include <algorithm>
#include <ctime>
#include <cctype>
#include <cmath>
#include <string>
#include <cstring>
#include <stack>
#include <queue>
#include <list>
#include <vector>
#include <map>
#include <set>
#define sqr(x) ((x)*(x))
#define LL long long
#define itn int
#define INF 0x3f3f3f3f
#define PI 3.1415926535897932384626
#define eps 1e-10

#ifdef _WIN32
  #define lld "%I64d"
#else
  #define lld "%lld"
#endif

#define maxm 100007
#define maxn 100007

using namespace std;

int fib[maxn];
struct _edge
{
  int u,v,w;
  bool operator < (const _edge &_)const
  {
    return w<_.w;
  }
}edge[maxm];

int pre[maxn];

int root(int x)
{
  if (x==pre[x]) return x;
  return pre[x]=root(pre[x]);
}

bool same(int x,int y)
{
  return root(x)==root(y);
}

void _merge(itn x,int y)
{
  pre[root(x)]=root(y);
}

int cnt,fib_cnt;

int main()
{
#ifdef FCBRUCE
  freopen("/home/fcbruce/code/t","r",stdin);
#endif // FCBRUCE

  int T_T,__=0;
  scanf("%d\n",&T_T);

  fib[0]=1;
  fib[1]=1;
  fib_cnt=2;
  for (int i=2;;i++)
  {
    fib[i]=fib[i-1]+fib[i-2];
    fib_cnt++;
    if (fib[i]>100000) break;
  }

  while (T_T--)
  {
    printf("Case #%d: ",++__);
    int n,m;
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++) pre[i]=i;
    cnt=n;
    for (int i=0,u,v,w;i<m;i++)
    {
      scanf("%d%d%d",&u,&v,&w);
      if (!same(u,v)) {_merge(u,v);cnt--;}
      edge[i]=(_edge){u,v,w};
    }

    if (cnt!=1)
    {
      printf("No\n");
      continue;
    }

    sort(edge,edge+m);

    for (int i=1;i<=n;i++) pre[i]=i;
    int MIN=0;
    cnt=n;
    for (int i=0,u,v,w;i<m;i++)
    {
      u=edge[i].u;v=edge[i].v;w=edge[i].w;
      if (!same(u,v))
      {
        _merge(u,v);
        MIN+=w;
        cnt--;
        if (cnt==1) break;
      }
    }

    for (int i=1;i<=n;i++) pre[i]=i;
    int MAX=0;
    cnt=n;
    for (int i=m-1,u,v,w;i>=0;i--)
    {
      u=edge[i].u;v=edge[i].v;w=edge[i].w;
      if (!same(u,v))
      {
        _merge(u,v);
        MAX+=w;
        cnt--;
        if (cnt==1) break;
      }
    }

    int idmin=lower_bound(fib,fib+fib_cnt,MIN)-fib;
    int idmax=lower_bound(fib,fib+fib_cnt,MAX)-fib;

    if (fib[idmin]!=MIN && fib[idmax]!=MAX && idmin==idmax)
      puts("No");
    else
      puts("Yes");

  }

  return 0;
}
时间: 2024-09-30 19:40:06

HDU 4786 Fibonacci Tree(生成树,YY乱搞)的相关文章

HDU 4786 Fibonacci Tree 生成树

链接:http://acm.hdu.edu.cn/showproblem.php?pid=4786 题意:有N个节点(1 <= N <= 10^5),M条边(0 <= M <= 10^5).当中一部分边被染成了黑色,剩下的边是白色,问能不能建立一棵树,树中有斐波那契数个白色边. 思路:用克鲁斯卡尔建三次树,第一是用全部边建树.推断能否建成一棵树,第二次用黑边建树,最多能够用到x条黑边(不成环),n-1-x就是最少须要用的白边的数量,第三次用白边建树,最多能够用到y条白边.假设在[y

HDU 4786 Fibonacci Tree 最小生成树变形

思路: 这题比赛的时候想了好久,最后队友机智的想到了. 不过那时不是我敲的,现在敲的1A. 想好就容易了. 直接把1或者0当做边的权值,然后按边从小到大排序,然后算最小生成用到了几条白边,然后再按边从大到小排序,然后再算白边用了几条.然后最小和最大需要用到的白边都算出来了.如果在这最小最大区间中存在那个啥数列的话就是Yes,否则就是No. 为什么在这区间里面就是对的呢?刚开始我也想了好久,然后发现,因为白边权值是1,然后黑边是0,然后假设用到白边最小的是6,最大的是10,那么,我们可以用黑边去替

HDU 4786 Fibonacci Tree 并查集+生成树=kruskal

Fibonacci Tree Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2149    Accepted Submission(s): 682 Problem Description Coach Pang is interested in Fibonacci numbers while Uncle Yang wants him t

hdu 4786 Fibonacci Tree ( 最小生成树 )

Fibonacci Tree Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2487    Accepted Submission(s): 796 Problem Description Coach Pang is interested in Fibonacci numbers while Uncle Yang wants him t

hdu 4786 Fibonacci Tree(最小生成树)

Fibonacci Tree Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2952    Accepted Submission(s): 947 Problem Description Coach Pang is interested in Fibonacci numbers while Uncle Yang wants him t

hdu 4786 Fibonacci Tree (最小、最大生成树)

题意: N个点,M条边.每条边连接两个点u,v,且有一个权值c,c非零即一. 问能否将N个点形成一个生成树,并且这棵树的边权值和是一个fibonacii数. (fibonacii数=1,2,3,5,8 .... ) 思路: 若可以生成一棵树.则有最小生成树和最大生成树.假设已经生成了最小MST  P 和最大MST  Q. 将P更换一条边可以得到另一棵生成树,边权和不是和P相等就是比P的边权和大1.(因为边值非零即一).同理搞下去....一定可以得到Q. 所以P的边权和到Q的边权和之间的所有值都能

HDU 4781 Assignment For Princess(YY乱搞)

http://acm.hdu.edu.cn/showproblem.php?pid=4781 Assignment For Princess Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 639    Accepted Submission(s): 196 Special Judge Problem Description Long

hdu 4786 Fibonacci Tree

题目:大致的意思就是说给定n个点和m条边,这m条边分成两种颜色----白色和黑色,问是否可以形成一个生成树使得白色边的个数是一个斐波那契数. 思路:求出白色边能形成的联通图(非环)的最多边数和最少边数.最大数能够用白边的并查集求得(max=num).而最少边数能够用黑边的并查集求的(min=n-1-num).然后再看在min--max之间是否存在斐波那契数就能够了. 解释:为什么这样求联通图的白边的个数区间是对的呢?首先上限就不用说了.那么我们想如果这个图可以形成生成树,这颗树里面除了白边就是黑

hdu 4786 Fibonacci Tree (最小生成树扩展)

///白边优先和黑边优先做两次最小生成树 ///若有斐波那契树在这中间为yes # include <stdio.h> # include <algorithm> # include <iostream> # include <string.h> # include <math.h> using namespace std; struct node { int x; int y; int v; }; struct node a[100010];