题目:
http://acm.hdu.edu.cn/showproblem.php?pid=4786题意:
给出一个图,其中的边有黑白两种,求是否可以找到白边数量为斐波那契数的生成树。
思路:
只有黑白边,白边为1,黑边为0,求出最小生成树和最大生成树的大小就是取白边的区间,二分找区间内是否存在斐波那契数就行了。代码:
#define N 1123456
#define M 1123456
int n,m;
int flag,sum,ave,ans1,ans2,res,cnt;
int a[N],b[N];
int f[N];
struct node
{
int u,v;
int r;
friend bool operator < (node a, node b)
{
return a.r < b.r;
}
}edge[M];
bool cmp1(node a,node b)
{
return a.r > b.r;
}
void inserts(int u,int v,int w)
{
edge[cnt].u = u;
edge[cnt].v = v;
edge[cnt++].r = w;
edge[cnt].u = v;
edge[cnt].v = u;
edge[cnt++].r = w;
}
void Init(int n)
{
for(int i=1;i<=n;i++)
f[i] = i;
}
int getf(int u)
{
if(f[u] != u)
f[u] = getf(f[u]);
return f[u];
}
bool unions(int x,int y)
{
x=getf(x);
y=getf(y);
if(x!=y)
{
f[x] = y;
return false;
}
return true;
}
int kruskal(int n,int m)
{
int i,k,res;
i=k=res=0;
while(k<n-1)
{
if(i == m)break;
if(!unions(edge[i].u,edge[i].v))
{
k++;
res+=edge[i].r;
}
i++;
}
return res;
}
void init()
{
a[0]=a[1]=1;
for(int i=2;i<45;i++)
a[i]=a[i-1]+a[i-2];
}
int main()
{
int i,j,k,kk,t,x,y,z;
scanf("%d",&k);
init();
kk=0;
while(k--)
{
cnt=0;
printf("Case #%d: ",++kk);
scanf("%d%d",&n,&m);
for(i=0;i<m;i++)
{
scanf("%d%d%d",&x,&y,&t);
inserts(x,y,t);
}
m*=2;
Init(n);
sort(edge,edge+m);
ans1=kruskal(n,m);
Init(n);
sort(edge,edge+m,cmp1);
ans2=kruskal(n,m);
flag=1;
for(i=1;i<=n;i++)
if(!unions(i,1))
{
printf("No\n");
flag=0;
break;
}
if(!flag)
continue;
res=*lower_bound(a,a+40,ans1);
if(res<=ans2&&res>=ans1)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}