思路是用二分来找到一个最大值,即单值最大
然后用最大生成树来求解结果即可
代码如下
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=200000+100;
struct node
{
int x,y;
long long w;
}tree[maxn*2];
int pre[maxn];
int n,m;
int cmp(node aa,node bb)
{
return aa.w>bb.w;
}
int findd(int x)
{
int r=x;
while(pre[r]!=r)
r=pre[r];
int i=x,j;
while(i!=r)
{
j=pre[i];
pre[i]=r;
i=j;
}
return r;
}
void join(int x,int y)
{
int tx=findd(x);
int ty=findd(y);
if(tx!=ty)
pre[tx]=ty;//如果改成pre[ty]=tx;,就超时。。。
}
int zyz(long long mid)
{
int i;
int ans=0;
for(i=0;i<=n;i++)
pre[i]=i;
for(i=0;i<m;i++)
{
if(tree[i].w<=mid)
{
if(findd(tree[i].x)!=findd(tree[i].y))
{
ans++;
join(tree[i].x,tree[i].y);
}
}
}
//cout<<ans<<endl;
if(ans==n-1)
return 1;
else
return 0;
}
int main ()
{
cin>>n>>m;
int i;
long long maxx=0;
for(i=0;i<m;i++)
{
scanf("%d%d%lld",&tree[i].x,&tree[i].y,&tree[i].w);
maxx=max(maxx,tree[i].w);
}
sort(tree,tree+m,cmp);
long long l=0;
long long r=maxx;
long long mid;
long long cnt=0;
while(l<=r)
{
mid=(l+r)/2;
//cout<<zyz(mid)<<endl;
if(zyz(mid))
{
r=mid-1;
cnt=mid;
}
else
{
l=mid+1;
}
}
for(i=0;i<=n;i++)
{
pre[i]=i;
}
//cout<<cnt<<endl;
long long sum=0;
for(i=0;i<m;i++)
{
if(tree[i].w<=cnt)
{
if(findd(tree[i].x)!=findd(tree[i].y))
{
sum+=tree[i].w;
join(tree[i].x,tree[i].y);
}
}
}
printf("%lld\n",sum);
}
有一个疑惑,不知道哪位大神可以解惑一下
就是在最大生成树(并查集解法)中,pre[ty]=tx,和pre[tx]=ty,时间复杂度不一样,后者比前者快一倍,不知道为什么!!!!