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代表黑边,求能否建一个生成树,使得白边的数量是一个斐波那契数列
思路:
由这些边建一棵最小生成树,权值和记为sum1,和一颗最大生成树,权值和为sum2,如果sum1与sum2之间存在一个斐波那契数,则输出Yes,否则输出No
我们知道由最小生成树到最大生成树的过度,必定是将其中的一条黑边删掉,加上了一条白边,而且保证了树的存在。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1e5+5;
struct node{
int u,v,w;
node(){
}
node(int uu,int vv,int ww){
u=uu;
v=vv;
w=ww;
}
bool operator<(const node other)const{
return w<other.w;
}
}edge[N*2];
int n,m;
int per[N];
void init(){
for(int i=0;i<N;i++)
per[i]=i;
}
int Find(int x){
return per[x]==x?x:per[x]=Find(per[x]);
}
int mix(int a,int b){
int fa=Find(a),fb=Find(b);
if(fa!=fb){
per[fa]=fb;
return 1;
}
return 0;
}
int solve1(){
init();
int ans=0,cnt=0;
for(int i=0;i<m;i++){
int u=edge[i].u;
int v=edge[i].v;
int w=edge[i].w;
if(mix(u,v)){
cnt++;
ans+=w;
}
if(cnt==n-1) break;
}
if(cnt==n-1) return ans;
else return 0;
}
int solve2(){
init();
int ans=0,cnt=0;
for(int i=m-1;i>=0;i--){
int u=edge[i].u;
int v=edge[i].v;
int w=edge[i].w;
if(mix(u,v)){
cnt++;
ans+=w;
}
if(cnt==n-1) break;
}
if(cnt==n-1) return ans;
return 0;
}
int fib[N];
void in(){
memset(fib,0,sizeof(fib));
int a=1;
int b=1;
fib[1]=1;
for(int i=2;i<=30;i++){
int c=a+b;
if(c>=N) break;
a=b;
b=c;
fib[c]=1;
}
}
int main(){
int T,cas=0;
scanf("%d",&T);
in();
while(T--){
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
edge[i]=node(u,v,w);
}
sort(edge,edge+m);
int mint=solve1();
int maxt=solve2();
int flag=0;
for(int i=mint;i<=maxt;i++)
if(fib[i]){
flag=1;
break;
}
printf("Case #%d: ",++cas);
if(flag) printf("Yes\n");
else printf("No\n");
}
return 0;
}