Fibonacci Tree(HDU - 4786)

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需要的白边数目,那么一定可以通过增删边得到[min,max]数量的白边的生成树。
这个是我看到题目就马上想到的想法,但证明的话也只能比较模棱两可的理论证明,没法具体给出有说服力的证明。只能说,当优先选取黑色边的时候,min是必须取的构造生成树的白边数目,因此之后的生成树都可以看作由这颗生成树增删边构成。
坑点就是给出的图不一定是连通图,还需要额外判断……WA了好几次。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <vector>
#include <iostream>
#include <string>
#include <map>
#include <stack>
#include <cstring>
#include <queue>
#include <list>
#include <stdio.h>
#include <set>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <iomanip>
#include <cctype>
#include <sstream>
#include <iterator>
#include <functional>
#include <stdlib.h>
#include <time.h>
#include <bitset>
using namespace std;

#define pi acos(-1)
#define s_1(x) scanf("%d",&x)
#define s_2(x,y) scanf("%d%d",&x,&y)
#define s_3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define s_4(x,y,z,X) scanf("%d%d%d%d",&x,&y,&z,&X)
#define s_5(x,y,z,X,Y) scanf("%d%d%d%d%d",&x,&y,&z,&X,&Y)
#define S_1(x) scan_d(x)
#define S_2(x,y) scan_d(x), scan_d(y)
#define S_3(x,y,z) scan_d(x), scan_d(y), scan_d(z)
#define PI acos(-1)
#define endl '\n'
#define srand() srand(time(0));
#define me(x,y) memset(x,y,sizeof(x));
#define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++)
#define close() ios::sync_with_stdio(0); cin.tie(0);
#define FOR(x,n,i) for(int i=x;i<=n;i++)
#define FOr(x,n,i) for(int i=x;i<n;i++)
#define fOR(n,x,i) for(int i=n;i>=x;i--)
#define fOr(n,x,i) for(int i=n;i>x;i--)
#define W while
#define sgn(x) ((x) < 0 ? -1 : (x) > 0)
#define bug printf("***********\n");
#define db double
#define ll long long
#define mp make_pair
#define pb push_back

#define mian main
#define ture true
typedef long long LL;
typedef pair <int, int> ii;
const int INF = 0x3f3f3f3f;
const LL LINF = 0x3f3f3f3f3f3f3f3fLL;
const int dx[] = {-1, 0, 1, 0, 1, -1, -1, 1, 0};
const int dy[] = {0, 1, 0, -1, -1, 1, -1, 1, 0};
const int maxn = 1e5 + 10;
const int maxx = 1e5 + 10;
const double EPS = 1e-9;
const double eps = 1e-9;
const int mod = 1e9 + 7;
template <class T> inline T min(T a, T b, T c) {return min(min(a, b), c);}
template <class T> inline T max(T a, T b, T c) {return max(max(a, b), c);}
template <class T> inline T min(T a, T b, T c, T d) {return min(min(a, b), min(c, d));}
template <class T> inline T max(T a, T b, T c, T d) {return max(max(a, b), max(c, d));}
template <class T> inline bool scan_d(T &ret) {
    char c;
    int sgn;
    if (c = getchar(), c == EOF) return 0;
    while (c != '-' && (c < '0' || c > '9')) c = getchar();
    sgn = (c == '-') ? -1 : 1;ret = (c == '-') ? 0 : (c - '0');
    while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return 1;
}
inline bool scan_lf(double &num) {
    char in;
    double Dec = 0.1;
    bool IsN = false, IsD = false;
    in = getchar();
    if (in == EOF) return false;
    while (in != '-' && in != '.' && (in < '0' || in > '9')) in=getchar();
    if (in == '-') {IsN = true; num = 0;}
    else if (in == '.') {IsD = true; num = 0;}
    else num = in - '0';
    if (!IsD) {
        while (in = getchar(), in >= '0' && in <= '9') {num *= 10; num += in - '0';}
    }
    if (in != '.') {
        if (IsN) num = -num;
        return true;
    }
    else{
        while (in = getchar(), in >= '0' && in <= '9') {
            num += Dec * (in - '0');
            Dec *= 0.1;
        }
    }
    if (IsN) num = num;
    return true;
}
void Out(LL a) {if(a < 0) {putchar('-'); a = -a;}if(a >= 10) Out(a / 10); putchar(a % 10 + '0');}
void print(LL a) {Out(a), puts("");}
/**********************************************WHITE_YASHA**********************************************/
//freopen( "in.txt" , "r" , stdin );
//freopen( "data.txt" , "w" , stdout );
//cerr << "run time is " << clock() << endl;
struct edge {
    int u, v, w;
    edge() {}
    edge(int _u, int _v, int _w) {
        u = _u;
        v = _v;
        w = _w;
    }
};
bool cmp_white(edge a, edge b) {return a.w > b.w;}
bool cmp_black(edge a, edge b) {return a.w < b.w;}
vector <edge> edges;
vector <int> fib;
int fa[maxn];
int t, n, m;
void fibonacci() {
    fib.pb(1); fib.pb(2);
    W (fib[fib.size() - 1] + fib[fib.size() - 2] <= maxx) {
        fib.pb(fib[fib.size() - 1] + fib[fib.size() - 2]);
    }
}
void init_fa() {
    FOR (1, n, i) fa[i] = i;
}
int find_fa(int x) {return fa[x] == x ? fa[x] : fa[x] = find_fa(fa[x]);}
void mix_fa(int x, int y) {
    int fx = find_fa(x), fy = find_fa(y);
    if (fx != fy) fa[fy] = fx;
}
int kruskal() {
    int ans = 0;
    init_fa();
    FOr (0, edges.size(), i) {
        if (find_fa(edges[i].u) != find_fa(edges[i].v)) {
            mix_fa(edges[i].u, edges[i].v);
            if (edges[i].w) ans++;
        }
    }
    return ans;
}
bool check() {
    init_fa();
    FOr (0, edges.size(), i) mix_fa(edges[i].u, edges[i].v);
    FOR (1, n, i) if (find_fa(i) != find_fa(1)) return false;
    return true;
}
int main() {
    fibonacci();
    s_1(t);
    FOR (1, t, cas) {
        edges.clear();
        init_fa();
        s_2(n, m);
        W (m--) {
            int u, v, w;
            s_3(u, v, w);
            edges.pb({u, v, w});
        }
        printf("Case #%d: ", cas);
        if (!check()) {
            puts("No");
            continue;
        }
        sort(edges.begin(), edges.end(), cmp_black);
        int minn = kruskal();
        sort(edges.begin(), edges.end(), cmp_white);
        int maxx = kruskal();
        puts(*lower_bound(fib.begin(), fib.end(), minn) <= maxx ? "Yes" : "No");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值