您的位置:首页 > 其它

hdoj 4786 Fibonacci Tree 【最小生成树 + 最大生成树】

2015-03-25 13:00 477 查看

Fibonacci Tree

[b]Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 2563 Accepted Submission(s): 817

[/b]

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


本题说的是:连通所有的点,且连通白边的数目须是fibonacci数列里面的数(可以有黑边,比如说黑3,白1就满足。并不是非得全是白边);

思路很简单:先按白——>黑排序,计算连通需要的最多的白边数目max;然后黑——>白排序,计算连通需要的最少的白边数目min;最后判断是否连通以及是否存在fibonacci数列里面的数fib[ i ]满足 min>= fib[ i ] <=max 。

ac代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define M 100000+1
using namespace std;
int set[M],fib[M];
struct line
{
    int start;
    int end;
    int judge;
}num[M];
bool cmp1(line a,line b)
{
    return a.judge>b.judge;//white放前面 
}
bool cmp2(line a,line b)
{
    return a.judge<b.judge;
}
void dabiao()
{
    int i,j;
    int t,sum;
    fib[1]=1;fib[2]=1;
    for(i=3;fib[i]<M;i++)
    {
        fib[i]=fib[i-1]+fib[i-2];
    }
}
int find(int p)
{
    int child=p;
    int t;
    while(p!=set[p])
    p=set[p];
    while(child!=p)
    {
        t=set[child];
        set[child]=p;
        child=t;
    }
    return p;
}
void merge(int x,int y)
{
    int fx=find(x);
    int fy=find(y);
    if(fx!=fy)
    set[fx]=fy;
}
int main()
{
    int t,n,m,i,j;
    int max,min;
    int k=1,exist,sum;
    memset(fib,0,sizeof(fib));
    dabiao();//fib[i]存储fibonacci数 
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++)
        set[i]=i;
        for(i=0;i<m;i++)
        {
            scanf("%d%d%d",&num[i].start,&num[i].end,&num[i].judge);
        }
        sort(num,num+m,cmp1);//white first
        max=0;
        for(i=0;i<m;i++)
        {
            if(find(num[i].start)!=find(num[i].end))
            {
                merge(num[i].start,num[i].end);
                if(num[i].judge)//white
                max++;
            }
        }
        min=0;
        sort(num,num+m,cmp2);//black first
        for(i=1;i<=n;i++)
        set[i]=i;
        for(i=0;i<m;i++)
        {
            if(find(num[i].start)!=find(num[i].end))
            {
                merge(num[i].start,num[i].end);
                if(num[i].judge)//white
                min++;
            }
        }
        exist=0;
        for(i=1;i<=n;i++)
        {
            if(set[i]==i)
            exist++;
            if(exist>1)
            break;
        }
        printf("Case #%d: ",k++);
        if(exist>1)//can not 
        {
            printf("No\n");
            continue;
        }
        exist=0;
        for(i=0;fib[i]<max;i++)
        {
            if(fib[i]>=min&&fib[i]<=max)
            {
                exist=1;
                break;
            }
        }
        if(exist)
        printf("Yes\n");
        else
        printf("No\n");
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: