HDU 4786 Fibonacci Tree 生成树

来源:互联网 发布:淘宝扫码怎么扫 编辑:程序博客网 时间:2024/04/28 01:51

链接: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,n-1-x】中有斐波那契数,则可以满足题意来建立这棵树。

代码:

#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <map>#include <cstdlib>#include <queue>#include <stack>#include <vector>#include <ctype.h>#include <algorithm>#include <string>#include <set>#define PI acos(-1.0)#define maxn 10005#define INF 0x7fffffff#define eps 1e-8typedef long long LL;typedef unsigned long long ULL;using namespace std;int root[100005];int findset(int x){    return x==root[x]?x:root[x]=findset(root[x]);}int Fib[40];void init(){    Fib[0]=1;    Fib[1]=1;    for(int i=2; i<=29; i++)        Fib[i]=Fib[i-1]+Fib[i-2];}struct edge{    int x,y;    int color;} e[100005];int Kruskal_w(edge e[],int m,int n,int f){    int sum=0;    for(int i=0; i<m; i++)        if(sum>=n-1)            break;        else if(e[i].color==f)        {            int xx=findset(e[i].x);            int yy=findset(e[i].y);            if(xx==yy)                continue;            else            {                if(xx<yy)                    root[yy]=xx;                else root[xx]=yy;                sum++;            }        }    return sum;}int Kruskal_a(edge e[],int m,int n,int &sum1){    int sum=0;    for(int i=0; i<m; i++)    {        if(sum1>=n-1)            break;        else if(e[i].color==1)        {            int xx=findset(e[i].x);            int yy=findset(e[i].y);            if(xx==yy)                continue;            else            {                if(xx<yy)                    root[yy]=xx;                else root[xx]=yy;                sum++;                sum1++;            }        }        else        {            int xx=findset(e[i].x);            int yy=findset(e[i].y);            if(xx==yy)                continue;            else            {                sum1++;                if(xx<yy)                    root[yy]=xx;                else root[xx]=yy;            }        }    }    return sum;}int main(){    int T;    scanf("%d",&T);    init();    for(int ii=1;ii<=T;ii++)    {        int n,m;        scanf("%d%d",&n,&m);        for(int i=0; i<m; i++)        {            scanf("%d%d",&e[i].x,&e[i].y);            scanf("%d",&e[i].color);        }        for(int i=0;i<=n;i++)            root[i]=i;        int sum1=Kruskal_w(e,m,n,1);        int sum2=0;        for(int i=0;i<=n;i++)            root[i]=i;        int sum3=Kruskal_a(e,m,n,sum2);        for(int i=0;i<=n;i++)            root[i]=i;        int sum4=Kruskal_w(e,m,n,0);        printf("Case #%d: ",ii);        bool flag=0;        if(sum2==n-1)        {            for(int i=0; i<=29; i++)            {                if(Fib[i]>=n-1-sum4&&Fib[i]<=sum1)                {                    flag=1;                    break;                }            }            if(flag)                printf("Yes\n");            else printf("No\n");        }        else printf("No\n");    }    return 0;}


0 0
原创粉丝点击