标签:
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
Case #1: Yes Case #2: No
2013 Asia Chengdu Regional Contest
有n个点,m条边,有黑白之分,问连通所有点时的边中,白边的个数能不能是斐波那契数列中的一个数
思路:先用白边连图,求出白边的个数,再先用黑边连图,求出白边另个值,,这两个值就是白边个数的取值范围 
2015,7,30 
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define M 100000+10
struct node{
	int s,e,val;
}sd[M];
int x[M];
int a[55];
bool cmp1(node a,node b){
	return a.val>b.val;
}
bool cmp2(node a,node b){
	return a.val<b.val;
}
void init()
{
	for(int i=0;i<M;i++)
		x[i]=i;	
}
int find(int k)
{
	if(x[k]==k) return k;
	x[k]=find(x[k]);
	return x[k];
}
int main()
{
	int t,m,n,v=1,i;
	int num,start,end;
	
	a[1]=1; a[2]=2;
	for(i=3;i<55;i++)//因为边最多有100000条,所以斐波那契数大于这个数时就可以了,55足够了 
		a[i]=a[i-1]+a[i-2];
		
	scanf("%d",&t);
	while(t--){
		scanf("%d%d",&n,&m);
		for(i=0;i<m;i++)
			scanf("%d%d%d",&sd[i].s,&sd[i].e,&sd[i].val);
			
		sort(sd,sd+m,cmp2);
		num=0; 	init();
		for(i=0;i<m;i++){
			int fa=find(sd[i].s);
			int fb=find(sd[i].e); 
			if(fa!=fb){
				x[fa]=fb;
				if(sd[i].val==1)
					num++;
			}
		}
		start=num;
		
		sort(sd,sd+m,cmp1);
		num=0;	init();
		for(i=0;i<m;i++){
			int fa=find(sd[i].s);
			int fb=find(sd[i].e); 
			if(fa!=fb){
				x[fa]=fb;
				if(sd[i].val==1)
					num++;
			}
		}
		end=num;
		
		int ok=0;
		for(i=1;i<=n;i++){
			if(find(i)!=find(1)){
				ok=1;
				break;
			}
		}
		printf("Case #%d: ",v++);
		if(ok) printf("No\n");//如果没有连通所有点直接输出No 
		else{
			for(i=1;i<50;i++){//注意这个i要从1开始,因为输入1个点0条边时要输出No,,我找了半天错= =+ 
				if(a[i]>= start && a[i]<=end){
					ok=1;
					break;
				}
			}
			if(ok) printf("Yes\n");
			else printf("No\n");
		}
	} 
	return 0;
}hdu 4786 Fibonacci Tree(最小生成树)
标签:
原文地址:http://blog.csdn.net/ling_du/article/details/47150135