hdu 4786 Fibonacci Tree【生成树相关】

来源:互联网 发布:db2 sql 编辑:程序博客网 时间:2024/04/28 07:26

Fibonacci Tree

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

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

Recommend

We have carefully selected several similar problems for you:  5921 5920 5919 5918 5917  


题目大意:


一共有N个点,M条无向边,其中每条边要么是白色的要么是黑色的(白色的用边权值为1表示),然后让你判断能否从图中找出一棵生成树,其中有n-1条边,其中白色的边的个数为斐波那契数,如果可行输出Yes,否则输出No。


思路:


1、吐槽一发这个题意..............看着区域赛的榜单顺序做的这个题,翻译完之后觉得是不能使用黑边的,题意确实很难真正透彻读懂...................


2、我们首先需要判断这样的图是否是连通的。如果当前图是不连通的,那么直接输出No,否则我们这样考虑:

①如果我们枚举一个斐波那契数num,表示当前生成树中的白色边的条数,那么我们很难确定如何找这num条白边,使得这个图尽量能够有一颗生成树。

②那么我们可以考虑极限情况,我们只要知道最少需要多少条白边,最多需要多少条白边,那么我们如果有一个斐波那契数<=maxn&&>=minn即可。

③minn求法:我们将所有黑色边都加入图中,这里用并查集连通即可,然后统计构成一颗生成树需要多少条白色边,这个统计的数,就是最少需要的边的个数。

④maxn求法:我们将所有白色边都加入图中,同样可以用并查集连通,然后统计最多需要多少条这样的白色边即可,统计出来的这个数,就是最多需要的边的个数。


Ac代码:


#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;struct node{    int x,y,w;}a[100050];int f[100050];int fi[10050];void init(){    fi[1]=1;    fi[2]=2;    int brek;    for(int i=3;i<=100;i++)    {        fi[i]=fi[i-1]+fi[i-2];        if(fi[i]>1000000)        {            brek=i;            break;        }    }}int find(int a){    int r=a;    while(f[r]!=r)    {        r=f[r];    }    int i=a;    int j;    while(i!=r)    {        j=f[i];        f[i]=r;        i=j;    }    return r;}void merge(int x,int y){    int xx=find(x);    int yy=find(y);    if(xx!=yy)    {        f[xx]=yy;    }}int cmp(node a,node b){    return a.w<b.w;}int cmp2(node a,node b){    return a.w>b.w;}int main(){    int t;    int kase=0;    init();    scanf("%d",&t);    while(t--)    {        int n,m;        scanf("%d%d",&n,&m);        for(int i=1;i<=n;i++)f[i]=i;        for(int i=0;i<m;i++)        {            scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].w);            merge(a[i].x,a[i].y);        }        int flag=0;        for(int i=2;i<=n;i++)        {            if(find(i)!=find(1))            {                flag=1;            }        }        printf("Case #%d: ",++kase);        if(flag==1)        {            printf("No\n");            continue;        }        for(int i=1;i<=n;i++)f[i]=i;        sort(a,a+m,cmp);        int minn=0;        for(int i=0;i<m;i++)        {            if(a[i].w==0)            {                if(find(a[i].x)!=find(a[i].y))                {                    merge(a[i].x,a[i].y);                }            }            else            {                if(find(a[i].x)!=find(a[i].y))                {                    merge(a[i].x,a[i].y);                    minn++;                }            }        }        for(int i=1;i<=n;i++)f[i]=i;        sort(a,a+m,cmp2);        int maxn=0;        for(int i=0;i<m;i++)        {            if(a[i].w==0)            {                if(find(a[i].x)!=find(a[i].y))                {                    merge(a[i].x,a[i].y);                }            }            else            {                if(find(a[i].x)!=find(a[i].y))                {                    merge(a[i].x,a[i].y);                    maxn++;                }            }        }        flag=0;        for(int i=1;i<=25;i++)        {            if(fi[i]>=minn&&fi[i]<=maxn)            {                printf("Yes\n"),flag=1;                break;            }        }        if(flag==0)        printf("No\n");    }}



0 0
原创粉丝点击