该题其实就是最小生成树的变形,先求一个最小生成树的权值,再求一个最大生成树的权值,显然在这两个权值之间的所有值都可以取到(你总可以拿一条黑边换成一条白边)。那么我们只要看一下这些值中有没有斐波那契数就行了。小于100000的斐波那契数只有几十个,直接枚举就行了 。
细节参见代码:
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const long long maxn = 100000 + 10;
int T,n,m,p[maxn],kase = 0,tot=0;
ll vis[maxn];
struct node{
int a,b,c;
bool operator < (const node& rhs) const {
return c < rhs.c;
}
}e[maxn];
int findd(int x) { return p[x] == x ? x : p[x] = findd(p[x]); }
void init() {
vis[0] = 1; vis[1] = 2;
tot = 2;
while(vis[tot-1] < 100000 + 500) {
vis[tot] = vis[tot-1]+vis[tot-2];
tot++;
}
}
bool solve() {
for(int i=1;i<=n;i++) p[i] = i;
sort(e,e+m);
int max_v = 0,min_v = 0 ,cnt = 1;
for(int i=0;i<m;i++) {
int x = findd(e[i].a) , y = findd(e[i].b);
if(x != y) {
cnt++;
min_v += e[i].c; p[x] = y;
}
}
if(cnt != n) return false;
for(int i=1;i<=n;i++) p[i] = i;
for(int i=m-1;i>=0;i--) {
int x = findd(e[i].a) , y = findd(e[i].b);
if(x != y) {
max_v += e[i].c; p[x] = y;
}
}
for(int i=0;i<tot;i++)
if(vis[i]>=min_v && vis[i]<=max_v) return true;
return false;
}
int main() {
init();
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++)
scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].c);
printf("Case #%d: ",++kase);
if(solve()) printf("Yes\n");
else printf("No\n");
}
return 0;
}