智商捉急。看了题解
先判断图是否联通,然后优先选黑边。看白边最小选多少,再优先选白边,看白边最多选多少。于是从最小到最大都可以构成这样的生成树了。
可以想象一下,既然已经可以联通成生成树了,那么黑边先选,再最小选出白边,一定存在许多白边可以替代黑边,多选一条白边,就一定找的出相应联通关系的黑边,一直到白边最多。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxl 100010
using namespace std;
int n,m,cas;
int f[maxl],fib[maxl];
struct ed{int x,y,w;} e[maxl];
bool yes;
bool cmp1(const ed &x,const ed &y)
{
return x.w<y.w;
}
bool cmp2(const ed &x,const ed &y)
{
return x.w>y.w;
}
void prework()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].w);
}
int find(int x)
{
if(f[x]!=x)
f[x]=find(f[x]);
return f[x];
}
int kru()
{
int cnt=0,x,y,sum=0;
for(int i=1;i<=n;i++)
f[i]=i;
for(int i=1;i<=m;i++)
{
x=find(e[i].x);y=find(e[i].y);
if(x!=y)
{
sum++;f[y]=x;cnt+=e[i].w;
if(sum==n-1)
break;
}
}
if(sum<n-1)
return -1;
return cnt;
}
void mainwork()
{
int l,r;yes=false;
sort(e+1,e+1+m,cmp1);
l=kru();
if(l==-1) return;
sort(e+1,e+1+m,cmp2);
r=kru();
fib[1]=1;
for(int i=2;i<=26;i++)
{
fib[i]=fib[i-1]+fib[i-2];
if(fib[i]>=l && fib[i]<=r)
yes=true;
}
}
void print()
{
if(yes)
printf("Case #%d: Yes\n",cas);
else
printf("Case #%d: No\n",cas);
}
int main()
{
int t;
scanf("%d",&t);
for(cas=1;cas<=t;cas++)
{
prework();
mainwork();
print();
}
return 0;
}