HDU 4786 Fibonacci Tree(思维最小生成树)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/GYH0730/article/details/82459854

Fibonacci Tree

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


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

求出最小生成树与最大生成树,统计白边的数量min,max,因为树的边权值为0或1,所以[min,max]区间里每一个数都存在一棵最小生成树与之对应,判断[min,max]中是否有斐波那契数就行了。注意给的图有可能不连通

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
const int INF = 0x3f3f3f3f;
typedef long long ll;
int a[30];
int pre[MAXN];
struct node
{
    int u,v,c;
}e[MAXN];
bool cmp1(struct node a,struct node b)
{
    return a.c > b.c;
}
bool cmp2(struct node a,struct node b)
{
    return a.c < b.c;
}
int Find(int x)
{
    if(x == pre[x]) return x;
    else return pre[x] = Find(pre[x]);
}
bool join(int x,int y)
{
    int fx = Find(x);
    int fy = Find(y);
    if(fx != fy) {
        pre[fy] = fx;
        return 1;
    }
    return 0;
}
int n;
void init()
{
    for(int i = 1; i <= n; i++) pre[i] = i;
}
int main(void)
{
    a[0] = 1,a[1] = 2;
    int num;
    for(int i = 2; i < 25; i++) {
        a[i] = a[i - 1] + a[i - 2];
        num = i;
        if(a[i] > 100000) break;
    }
    int T;
    int m;
    scanf("%d",&T);
    int kase = 0;
    while(T--) {
        kase++;
        scanf("%d %d",&n,&m);
        for(int i = 1; i <= m; i++) {
            scanf("%d %d %d",&e[i].u,&e[i].v,&e[i].c);
        }
        sort(e + 1,e + 1 + m,cmp1);
        init();
        int c1 = 0,c2 = 0;
        int cnt = 0;
        for(int j = 1; j <= m; j++) {
            int u = e[j].u,v = e[j].v;
            if(join(u,v)) {
                if(e[j].c) c1++;
                cnt++;
            }
        }
        if(cnt != n - 1) {
            printf("Case #%d: No\n",kase);
            continue;
        }
        sort(e + 1,e + 1 + m,cmp2);
        init();
        for(int j = 1; j <= m; j++) {
            int u = e[j].u,v = e[j].v;
            if(join(u,v)) {
                if(e[j].c) c2++;
            }
        }
        int flag = 0;
        for(int i = 0; i < num; i++) {
            if(c2 <= a[i] && a[i] <= c1) {
                flag = 1;
                break;
            }
        }
        //printf("%d %d\n",c1,c2);
        if(flag) printf("Case #%d: Yes\n",kase);
        else printf("Case #%d: No\n",kase);
    }
    return 0;
}
/*
22
1 0
Case #1: No
5 10
1 2 1
1 3 1
2 4 1
3 5 1
2 4 0
3 5 1
2 4 0
2 4 0
1 3 1
2 5 1
Case #2: No
*/

猜你喜欢

转载自blog.csdn.net/GYH0730/article/details/82459854
今日推荐