HDU-4786 Fibonacci Tree(最小生成树[Kruskal])

来源:互联网 发布:淘宝商标注册号怎么填 编辑:程序博客网 时间:2024/04/29 00:00

Fibonacci Tree

Time Limit : 4000/2000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other)

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

24 41 2 12 3 13 4 11 4 05 61 2 11 3 11 4 11 5 13 5 14 2 1

Sample Output

Case #1: YesCase #2: No

区域赛都是有思维难度的题吧,果然还是不够熟悉图,完全没有思路。

看了别人的题解也才知道:

如果一棵生成树最少含有low条白边,最多含有hig条白边,那么含有x(low<=x&&x<=hig)条白边的生成树一定存在

不知道为什么中间的每一个生成树都存在(望大神告知),但我自己画了几个图还没找出反例


#include <cstdio>#include <algorithm>using namespace std;struct Edge {    int s,e,c;    Edge(int ss=0,int ee=0,int cc=0):s(ss),e(ee),c(cc) {}    bool operator < (const Edge& a) const {        return c<a.c;    }}g[100005];int par[100005],pa,pb,f[25];int getPar(int a) {    if(par[a]!=a)        par[a]=getPar(par[a]);    return par[a];}void Merge(int a,int b) {    pa=getPar(a),pb=getPar(b);    if(pa!=pb)        par[pb]=pa;}int main() {    int n,m,i,T,kase=0,cnt,low,hig;    bool flag;    i=1,f[0]=1,f[1]=2;    while(f[i]<100005) {        f[i+1]=f[i]+f[i-1];        ++i;    }    scanf("%d",&T);    while(kase<T) {        scanf("%d%d",&n,&m);        low=hig=0,cnt=1;        for(i=0;i<m;++i)            scanf("%d%d%d",&g[i].s,&g[i].e,&g[i].c);        for(i=1;i<=n;++i)            par[i]=i;        sort(g,g+m);        for(i=0;i<m&&cnt!=n;++i) {            if(getPar(g[i].s)!=getPar(g[i].e)) {                Merge(g[i].s,g[i].e);                ++cnt;                low+=g[i].c;            }        }        flag=false;        if(cnt==n) {//如果图是连通的            cnt=1;            for(i=1;i<=n;++i)                par[i]=i;            for(i=m-1;i>=0&&cnt!=n;--i) {                if(getPar(g[i].s)!=getPar(g[i].e)) {                    Merge(g[i].s,g[i].e);                    ++cnt;                    hig+=g[i].c;                }            }            i=0;            while(f[i]<low)                ++i;            if(f[i]<=hig)                flag=true;        }        printf("Case #%d: %s\n",++kase,flag?"Yes":"No");    }    return 0;}


0 0