F - 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 <= 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
题意
给你一个无向图,n个顶点,m条边,其中有白边(1)和黑边(0),问能不能生成一个树,所使用的白边的数量是斐波那契数。
分析
最小生成树,优先使用黑边,统计使用黑边的数量,白边使用数量为(n-1-黑边使用数量),找到比白边使用数量稍大的斐波那契数tmp,如果tmp大于n-1,那么输出“No”;如果小于n-1,白边总数大于tmp输出“Yes”,否则输出“No”。
代码
#include<iostream>
#include<cstdio>
#include<string.h>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=1e5+5;
int n,m;
int pre[N],f[36];
struct node{
int left,right;
int val;
}mp[N];
bool cmp(const node x,const node y)
{
return x.val<y.val;
}
void init()
{
for(int i=0;i<N;i++)
pre[i]=i;
}
int find(int x)
{
int r=x;
while(r!=pre[r])
r=pre[r];
int tmp,a=x;
while(a!=r)
{
tmp=pre[a];
pre[a]=r;
a=tmp;
}
return r;
}
void unionn(int x,int y)
{
pre[find(y)]=find(x);
}
int main()
{
int t;
cin>>t;
int cas=1;
f[1]=1;
f[2]=1;
for(int i=3;i<36;i++)
f[i]=f[i-1]+f[i-2];
while(t--)
{
init();
scanf("%d%d",&n,&m);
int b=0,w=0;
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&mp[i].left,&mp[i].right,&mp[i].val);
if(mp[i].val==0) b++;
else w++;
}
sort(mp,mp+m,cmp);
int cnt=0,flag=0,sum=0;
for(int i=0;i<m;i++)
{
if(find(mp[i].left)!=find(mp[i].right))
{
cnt++;
unionn(mp[i].left,mp[i].right);
if(mp[i].val==0)
sum++;
if(cnt==n-1)
{
flag=1;
break;
}
}
}
printf("Case #%d: ",cas++);
if(!flag)
{
printf("No\n");
continue;
}
int cha=n-1-sum;//使用白边的数量
int tmp;
for(int i=1;i<36;i++)
{
if(f[i]>=cha)
{
tmp=f[i];
break;
}
}
if(tmp>n-1)
printf("No\n");
else
{
if(w>=tmp) printf("Yes\n");
else printf("No\n");
}
}
return 0;
}