hdu 4786 Fibonacci Tree 思路

来源:互联网 发布:怎样在淘宝网卖闲置品 编辑:程序博客网 时间:2024/06/06 16:54

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 <= 10 5) and M(0 <= M <= 10 5). 
  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

24 41 2 12 3 13 4 11 4 05 61 2 11 3 11 4 11 5 13 5 14 2 1

Sample Output

Case #1: Yes

Case #2: No

题意:

给你n个点,m条边,边有黑白两种颜色,问能否用这些边组成一个生成树,使其白色的边的个数为斐波拉切数(1,2,3,5)?

解题思路:

先用 kruskal跑一遍看图是否连通。然后只用白色边构图(用kruskal跑),看最多能用多少白色边(max),然后只用黑色边构图,看最少能用多少白色边(min)。最后枚举斐波拉切数,看是否有在这个范围内成立的斐波拉切数。

为什么找到了max图和min图就能保证一定存在这之间任意数量的白色边的图?

考察min图,加入一条未被用过的白色边,有两种情况

1:这个加入的边刚好覆盖在一条黑色边上,删除此黑色边即可得到min+1的图;

2:这个边没有覆盖任何边,那么只要能从联通这个边的两个节点的通路上删除一条黑色边,就可以min+1的图。假设不存在min+1的图,那么此通路上的所有边都是白色,那么直到把所有白色边都加入图中,任意白色边的两个端点间的通路就都没有黑色边。那么就会得到这样一种情况,最多只有一个节点既能连白色边,又能连黑色边,删除此节点,则得到两个不相连图,一个全是黑色边,一个全是白色边。对于这种情况,可以推出max=min,也就是说只要max>min,这个假设就是错的,所以min+1的图一定存在。

继续考察min+1的图,同上证明。。。可以证明白色边数量在min-max之间所有的图都存在。

好烦人的题目。。。

代码:

#include <iostream>#include <string.h>#include <stdio.h>#include <algorithm>#define maxn 100010using namespace std;int f[maxn],febo[50];int n,m;struct edge{    int u,v,c;}e[maxn];int find(int x){    return f[x]==x?x:f[x]=find(f[x]);}int solve(int col){    int num=0;    for(int i=1;i<=n;i++)f[i]=i;    for(int i=1;i<=m;i++)    {        if(e[i].c!=col)        {            int x=find(e[i].u),y=find(e[i].v);            if(x!=y)            {                f[x]=y;                num++;            }        }    }    return num;}int main(){    febo[0]=1,febo[1]=2;    int num;    for(num=2;;num++)    {        febo[num]=febo[num-1]+febo[num-2];        if(febo[num]>100000)        break;    }    int ncase,T=0;    scanf("%d",&ncase);    while(ncase--)    {        printf("Case #%d: ",++T);        scanf("%d%d",&n,&m);        for(int i=1;i<=m;i++)        scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].c);        int tmp,mi,ma,tru=0;        tmp=solve(2);        if(tmp!=n-1)        {            printf("No\n");            continue;        }        ma=solve(0);        mi=n-1-solve(1);        for(int i=0;i<num;i++)        {            if(febo[i]>=mi&&febo[i]<=ma)            {                tru=1;                break;            }        }        if(tru)        printf("Yes\n");        else        printf("No\n");    }    return 0;}


0 0
原创粉丝点击