qdu17级区域赛组队训练7-1_2013成都

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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值