链接:http://acm.hdu.edu.cn/showproblem.php?pid=4786
题意:有N个节点(1 <= N <= 10^5),M条边(0 <= M <= 10^5)。当中一部分边被染成了黑色,剩下的边是白色,问能不能建立一棵树,树中有斐波那契数个白色边。
思路:用克鲁斯卡尔建三次树,第一是用全部边建树。推断能否建成一棵树,第二次用黑边建树,最多能够用到x条黑边(不成环),n-1-x就是最少须要用的白边的数量,第三次用白边建树,最多能够用到y条白边。假设在【y,n-1-x】中有斐波那契数,则能够满足题意来建立这棵树。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <map> #include <cstdlib> #include <queue> #include <stack> #include <vector> #include <ctype.h> #include <algorithm> #include <string> #include <set> #define PI acos(-1.0) #define maxn 10005 #define INF 0x7fffffff #define eps 1e-8 typedef long long LL; typedef unsigned long long ULL; using namespace std; int root[100005]; int findset(int x) { return x==root[x]?x:root[x]=findset(root[x]); } int Fib[40]; void init() { Fib[0]=1; Fib[1]=1; for(int i=2; i<=29; i++) Fib[i]=Fib[i-1]+Fib[i-2]; } struct edge { int x,y; int color; } e[100005]; int Kruskal_w(edge e[],int m,int n,int f) { int sum=0; for(int i=0; i<m; i++) if(sum>=n-1) break; else if(e[i].color==f) { int xx=findset(e[i].x); int yy=findset(e[i].y); if(xx==yy) continue; else { if(xx<yy) root[yy]=xx; else root[xx]=yy; sum++; } } return sum; } int Kruskal_a(edge e[],int m,int n,int &sum1) { int sum=0; for(int i=0; i<m; i++) { if(sum1>=n-1) break; else if(e[i].color==1) { int xx=findset(e[i].x); int yy=findset(e[i].y); if(xx==yy) continue; else { if(xx<yy) root[yy]=xx; else root[xx]=yy; sum++; sum1++; } } else { int xx=findset(e[i].x); int yy=findset(e[i].y); if(xx==yy) continue; else { sum1++; if(xx<yy) root[yy]=xx; else root[xx]=yy; } } } return sum; } int main() { int T; scanf("%d",&T); init(); for(int ii=1;ii<=T;ii++) { int n,m; scanf("%d%d",&n,&m); for(int i=0; i<m; i++) { scanf("%d%d",&e[i].x,&e[i].y); scanf("%d",&e[i].color); } for(int i=0;i<=n;i++) root[i]=i; int sum1=Kruskal_w(e,m,n,1); int sum2=0; for(int i=0;i<=n;i++) root[i]=i; int sum3=Kruskal_a(e,m,n,sum2); for(int i=0;i<=n;i++) root[i]=i; int sum4=Kruskal_w(e,m,n,0); printf("Case #%d: ",ii); bool flag=0; if(sum2==n-1) { for(int i=0; i<=29; i++) { if(Fib[i]>=n-1-sum4&&Fib[i]<=sum1) { flag=1; break; } } if(flag) printf("Yes\n"); else printf("No\n"); } else printf("No\n"); } return 0; }
时间: 2024-11-03 01:37:05