题意:
题目的意思是给你一些白色边和黑色边,现在问你能否用两色边构造出一颗生成树,且树中白色边的数量为一个Fibonacci数。
思路:
构造最大生成树和最小生成树;
先去判断是否为联通图,不联通的就输出NO
计算里面白边的值,看在这个范围内有没有Fibonacci的数
CODE
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<iostream>
#include<math.h>
#define MAX 100010
using namespace std;
int f[MAX*2];
int F[MAX];
int n, m;
int op;
struct node
{
int u, v, w;
} ls[MAX*2];
bool cm1(node a,node b)
{
return a.w < b.w;
}
bool cm2(node a,node b)
{
return a.w > b.w;
}
int find(int x)
{
return f[x] == x ? x:f[x]=find(f[x]);
}
void kruskal()
{
sort(ls,ls+m,cm1);
int i;
for(i = 0; i <= n; i++)
f[i] = i;
int cnt = 0;
for(i = 0; i < m; i++)
{
int x = find(ls[i].u), y = find(ls[i].v);
if(x!=y)
{
f[x] = y;
if(ls[i].w == 1)
cnt++;
}
}
int l = cnt;
sort(ls,ls+m,cm2);
for(i = 0; i <= n; i++)
f[i] = i;
cnt = 0;
for(i = 0; i < m; i++)
{
int x = find(ls[i].u), y = find(ls[i].v);
if(x!=y)
{
f[x] = y;
if(ls[i].w == 1)
cnt++;
}
}
int h = cnt;
bool ff = true;
for(int i = 1; i <= n; i++)
if(find(i) != find(1))
{
ff = false;
break;
}
if(!ff)
{
printf("No\n");
return ;
}
bool flag = false;
for(int i = 0; i <= op; i++)
if(F[i] >= l && F[i] <= h)
flag = true;
if(flag)
printf("Yes\n");
else printf("No\n");
}
int main()
{
F[0] = 1;
F[1] = 2;
op = 1;
for(int i = 2; F[i-1]+F[i-2] <= MAX; i++)
{
F[i] = F[i-1] + F[i-2];
op = i;
}
int t;
scanf("%d",&t);
int io = 1;
while(t--)
{
scanf("%d%d",&n,&m);
int i;
for(i = 0; i < m; i++)
{
int u, v, w;
scanf("%d%d%d",&u,&v,&w);
ls[i].u = u;
ls[i].v = v;
ls[i].w = w;
}
printf("Case #%d: ",io++);
kruskal();
}
return 0;
}