最小生成树

来源:互联网 发布:做网络直播需要什么设备 编辑:程序博客网 时间:2024/06/06 01:57

Problem Description

  Coach Pang is interested in Fibonaccinumbers while Uncle Yang wants him to do some research on Spanning Tree. SoCoach Pang decides to solve the following problem:
  Consider a bidirectional graph G with N vertices andM edges. All edges are painted into either white or black. Can we find aSpanning 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 inputcontains an integer T, the number of test cases.
  For each test case, the first line contains twointegers N(1 <= N <= 105) and M(0 <= M <= 105).
  Then M lines follow, each contains three integers u,v (1 <= u,v <= N, u<> v) and c (0 <= c <= 1), indicating anedge 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” (withoutquotes) 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


给出m个点n条边,每条边不是白色就是黑色,判断用这些边能不能构建一个生成树,并且判断白边的条数是不是一个斐波那契数

最小生成树问题,判断首先能不能构建生成树,n个点,则最少需要n-1条边即可,在并查集中判断两点是否属于一个集合。首先让白边优先判断使用白边数,然后黑边优先,判断使用的白边数,然后在题目范围内判断在最小的白边数与最大的白边数中是否含有斐波那契数,含有的话输出Yes,否则输出No

最小生成树问题应该首先判断能不能联通即能不能构建一个生成树


#include<stdio.h>#include<algorithm>using namespace std;struct edge{int u;int v;int w;}e[100010];int f[100010],f1[100010],s=0;int cmp(edge a,edge b){return a.w<b.w;}int cmp1(edge a,edge b){return a.w>b.w;}int find(int v) {if(v==f[v])return v;else{f[v]=find(f[v]);return f[v];}}int find1(int v){if(v==f1[v])return v;else{f1[v]=find1(f1[v]);return f1[v];}}int unite(int x,int y){int t1,t2;t1=find(x);t2=find(y);if(t1!=t2){f[t1]=t2;s++;return 1;}return 0;}int unite1(int x,int y){int t1,t2;t1=find1(x);t2=find1(y);if(t1!=t2){f1[t1]=t2;return 1;}return 0;}int main(){int t,n,m,i,count,sum,sum1,count1,fei[100010],flag,k,kk=0;fei[0]=0;fei[1]=1;fei[2]=2;for(i=3;;i++){fei[i]=fei[i-1]+fei[i-2];if(fei[i]>100010){k=i;break;}}scanf("%d",&t);while(t--){s=0;kk++;flag=0;count=0;sum=0;scanf("%d%d",&n,&m);for(i=0;i<m;i++)scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);sort(e,e+m,cmp1);for(i=1;i<=n;i++)f[i]=i;for(i=0;i<m;i++){if(unite(e[i].u,e[i].v)){count++;if(e[i].w==1)sum++;}if(count==n-1)break;}for(i=1;i<=n;i++)f1[i]=i;sort(e,e+m,cmp);sum1=0,count1=0;for(i=0;i<m;i++){if(unite1(e[i].u,e[i].v)){count1++;if(e[i].w==1)sum1++;}if(count1==n-1)break;}//printf("%d\n",sum);//printf("%d\n",sum1);for(i=1;i<=k;i++){if(fei[i]>=sum1 && fei[i]<=sum){flag=1;break;}}if(s<n-1)printf("Case #%d: No\n",kk);else{if(flag==1)printf("Case #%d: Yes\n",kk);elseprintf("Case #%d: No\n",kk);}}return 0;}