Fibonacci Tree

这篇博客探讨了Fibonacci Tree问题,作者在解决过程中遇到代码错误,尽管思路与他人相似,但自己编写的代码未能通过验证。问题要求在给定的边集中,判断生成树的白色边数是否包含Fibonacci数。作者尝试使用Kruskal算法,通过排序边来确定白边数量的范围,并用二分搜索在Fibonacci数列中查找。然而,最初的实现未能通过所有测试用例,最终作者采用了不同的方法,创建一个布尔数组来标记100000内的Fibonacci数,从而判断白边数量是否包含Fibonacci数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Fibonacci Tree

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


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 <= 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
  
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

这道题特别郁闷,明明感觉没错的啊,跟别人写的也几乎差不多啊(刚开始是思路差不多,到后米变成代码差不多了),但是依旧有错,最后把别人的代码粘贴过来改成我定义的一些字符,提交就对了,但是提交我自己的与他的几乎一样的代码,还是wrong,不过不想管那么多了。

这个题的意思是给定一些点边,有些边为白色即为1,有些边为黑色即为0,要求所有生成树中,含有白色边的条数是否有Fibonacci数列中的数,如果有则输出yes,否则输出no.也就是求生成树时所用到的白边范围中是否含有Fibonacci数,用kruskal来求得所用白边的数量,先对边进行排序,以黑色为主的升序排序,计算出需要用到白边的最小数量aa,以白色为主的降序排序,计算出需要用到白边的最大数量bb,最后在这个范围内查询是否含有Fibonacci数,最初我的想法是把小于等于100000的Fibonacci数装在一个数组李,只有24个数(第24个已经是大于100000的了),然后用二分的方法来查询比aa大的所有数中最小的那个数,然后与bb比较,如果小于等于则输出yes,否则输出no。但是程序一直错,最后不得不换为这个方法,定义一个长为100000的fib数组,是Fibonacci数的那一位则赋值为true,不是的都是false。


//这个是我用别人的代码改的,是对的

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int fa[110000];
bool fib[110000];
struct node
{
    int st,en,co;
}e[110000];
int Find(int x)
{
    if(fa[x]==x) return x;
    else return fa[x]=Find(fa[x]);
}
bool cmp1(node a,node b)
{
    return a.co<b.co;
}
bool cmp2(node a,node b)
{
    return a.co>b.co;
}
void Fibonacci()                                     //预处理Fibonacci数组
{
    memset(fib,false,sizeof(fib));
    int a=1,b=2,c;
    fib[a]=fib[b]=true;
    while(1)
    {
        c=a+b;
        if(c>100000) break;
        fib[c]=true;
        a=b,b=c;
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    Fibonacci();
    for(int k=1;k<=T;k++)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
            scanf("%d%d%d",&e[i].st,&e[i].en,&e[i].co);
        int ans1=0,ans2=0;
        sort(e+1,e+m+1,cmp1);                               //以黑边为主的排序
        for(int i=1;i<=n;i++) fa[i]=i;
        for(int i=1;i<=m;i++)
        {
            int fx=Find(e[i].st),fy=Find(e[i].en);
            if(fx!=fy)
            {
                if(e[i].co) ans1++;                                     //如果是白边则加1
                fa[fx]=fy;
            }
        }
        int fg=1,tem=Find(1);
        for(int i=2;i<=n;i++)
        {
            if(Find(i)!=tem)
            {
                fg=0;
                break;
            }
        }
        if(!fg)
        {
            printf("Case #%d: No\n",k);
            continue;
        }
        sort(e+1,e+m+1,cmp2);                                      //以白边为主的排序
        for(int i=1;i<=n;i++) fa[i]=i;
        for(int i=1;i<=m;i++)
        {
            int fx=Find(e[i].st),fy=Find(e[i].en);
            if(fx!=fy)
            {
                if(e[i].co) ans2++;
                fa[fx]=fy;
            }
        }
        fg=0;
        for(int i=ans1;i<=ans2;i++)                        //从最小数到最大数依次与fib数组的数相比较
        {
            if(fib[i])
            {
                fg=1;
                break;
            }
        }
        if(fg) printf("Case #%d: Yes\n",k);
        else printf("Case #%d: No\n",k);
    }
    return 0;
}




//下面的是我自己敲的代码,是错的

#include <iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int fa[110000];
bool fib[110000];
struct node
{
    int st,en,len;
}e[110000];
int Find(int x)
{
    if(x==fa[x]) return x;
    else return fa[x]=Find(fa[x]);
}
bool cmp1(node n1,node n2)
{
    return n1.len<n2.len;
}
bool cmp2(node n1,node n2)
{
    return n1.len>n2.len;
}
void Fibonacci()
{
    memset(fib,false,sizeof(fib));
    int a=1,b=2,c;
    fib[1]=true;
    fib[2]=true;
    while(1)
    {
        c=a+b;
        if(c>100000) break;
        fib[c]=true;
        a=b;
        b=c;
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    Fibonacci();
    for(int k=1;k<=T;k++)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&e[i].st,&e[i].en,&e[i].len);
        }
        int aa=0,bb=0;
        sort(e+1,e+m+1,cmp1);
        for(int i=1;i<=n;i++) fa[i]=i;
        for(int i=1;i<=m;i++)
        {
            int x=Find(e[i].st),y=Find(e[i].en);
            if(x!=y)
            {
                if(e[i].len) aa++;
                fa[x]=y;
            }
        }
        int flag=1,tem=Find(1);
        for(int i=2;i<=n;i++)
        {
            if(Find(i)!=tem)
            {
                flag=0;
                break;
            }
        }
        if(!flag)
        {
            printf("Case #%d: NO\n",k);
            continue;
        }
        sort(e+1,e+m+1,cmp2);
        for(int i=1;i<=n;i++) fa[i]=i;
        for(int i=1;i<=m;i++)
        {
            int x=Find(e[i].st),y=Find(e[i].en);
            if(x!=y)
            {
                if(e[i].len) bb++;
                fa[x]=y;
            }
        }
        flag=0;
        for(int i=aa;i<=bb;i++)
        {
            if(fib[i])
            {
                flag=1;
                break;
            }
        }
        if(flag)
            printf("Case #%d: Yes\n",k);
        else printf("Case #%d: NO\n",k);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值