题意:
给你一个N个点,M条边的图,边的颜色有白色和黑色,求是否存在一个Spanning tree 的白边的数目是斐波拉契数
方法:
求出生成树最少使用多少条白边和至多使用多少条白边即可,然后判断区间是否有斐波拉契数
PS:
图论做的比较少,懂的东西太少,连Spanning tree 都不知道是什么,猜题意猜了半天还是猜错了。。。。
图的生成树和最小生成树: http://blog.csdn.net/heavenboya/article/details/6654778
代码:
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define maxn 200010 struct node { int u, v, c; node(int a, int b, int c): u(a),v(b),c(c){} node(){} }edge[maxn]; int n, m,min_1,max_1,tot, ans; int prime[30],father[maxn]; bool cmp(node x, node y) { return x.c< y.c; } bool cmptwo(node x, node y) { return x.c> y.c; } int find(int x) { return x== father[x]? x: father[x]= find(father[x]); } void primee(int &mm) { mm= 0; int i= 1, j= 1; while(i< n && j<= tot) { int v1= find(edge[j].u); int v2= find(edge[j].v); if(v1!= v2) { father[v2]= v1; mm+= edge[j].c; i++; } j++; } if(i< n) ans= -1; } int main() { // freopen("in.txt","r",stdin); prime[1]= 1, prime[2]= 2; for(int i= 2; prime[i]<= 100000; i++) prime[i+1]= prime[i]+ prime[i-1]; int T; scanf("%d",&T); for(int C= 1; C<= T; C++) { scanf("%d %d",&n,&m); int a, b, c; tot= ans= 0; for(int i= 1; i<= m; i++) { scanf("%d %d %d",&a,&b,&c); edge[++tot]= node(a,b,c); } sort(edge+1, edge+tot+1, cmp); for(int i= 1; i<= n; i++) father[i]= i; primee(min_1); sort(edge+1, edge+tot+1, cmptwo); for(int i= 1; i<= n; i++) father[i]= i; primee(max_1); printf("Case #%d: ",C); if(ans== -1) { printf("No\n"); continue; } for(int i= 1; prime[i]<= max_1; i++) if(prime[i]>= min_1 && prime[i]<= max_1) { ans= 1; break; } if(ans) printf("Yes\n"); else printf("No\n"); } return 0; }