HDU4786 Fibonacci Tree【最小生成树+并查集+kruskal】

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.

思路:Fibonacci序列打表,然后求出最小生成树再求最大生成树,如果最小生成树和最大生成树之间找不到fibonacci值,说明构成不了fibonacci树。

代码:

#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
#define qx std::ios::sync_with_stdio(false)
using namespace std;

struct Node{
    int u,v,c;
}no[100010];
int p[10100],n,m,Fibo[100100];
int cmp(Node i,Node j){return i.c<j.c;}
int f(int x){return p[x]==x?x:p[x]=f(p[x]);}
int Fibonaci(){
    Fibo[1] = 1;
    Fibo[2] = 2;
    for(int i = 3; Fibo[i] <= 100100; ++i){
        Fibo[i] = Fibo[i-1] + Fibo[i-2];
        if(Fibo[i]>=100000)return i;
    }
}
int krus1(){
    for(int i=0;i<=n;i++)p[i]=i;
    int ans=0,k=0;
    for(int i=0;i<m;i++){
        int x=f(no[i].u),y=f(no[i].v);
        if(x!=y){
            p[x]=y;
            ans+=no[i].c;
            k++;
        }
        if(k==n-1)break;
    }
    if(k==n-1)return ans;
    else return 0;
}
int krus2(){
    for(int i=0;i<=n;i++)p[i]=i;
    int ans=0,k=0;
    for(int i=m-1;i>=0;i--){
        int x=f(no[i].u),y=f(no[i].v);
        if(x!=y){
            p[x]=y;
            ans+=no[i].c;
            k++;
        }
        if(k==n-1)break;
    }
    if(k==n-1)return ans;
    else return 0;
}
int main(){
    int t,h=1;qx;
    cin>>t;
    int g=Fibonaci();
    while(t--){
        cin>>n>>m;
        for(int i=0;i<m;i++){
            cin>>no[i].u>>no[i].v>>no[i].c;
        }
        sort(no,no+m,cmp);
        int a=krus1();
        int b=krus2();
        int flag=0;
        for(int i=a;i<=b;i++){
            if(flag)break;
            for(int j=1;j<g;j++){
                if(i==Fibo[j]){
                    flag=1;
                    break;
                }
            }
        }
        if(flag)cout<<"Case #"<<h<<": Yes"<<endl;
        else cout<<"Case #"<<h<<": No"<<endl;
        h++;
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值