在满足魔法值最大值尽可能小的情况下,魔力值之和尽可能的大
魔力值最大值尽可能的小,那么这个值不超过最小生成树的最大权值
在不超过最小生成树的最大权值的所有边中选取n-1条边组成最大生成树即可
注意下数据范围
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define N 1000005
#define inf 0x3f3f3f3f
using namespace std;
int pre[N];
int n,m,maxn;
struct stu
{
int s;
int e;
int w;
}map[N];
init()
{
for(int i=1;i<=n;i++)
pre[i]=i;
}
bool cmp(stu x,stu y)
{
return x.w<y.w;
}
bool cmp1(stu x,stu y)
{
return x.w>y.w;
}
int find(int x)
{
int r=x;
while(r!=pre[r])
{
r=pre[r];
}
int i=x,j;
while(pre[i]!=r)
{
j=pre[i];
pre[i]=r;
i=j;
}
return r;
}
bool join(int x,int y)
{
int fx=find(x);
int fy=find(y);
if(fx!=fy)
{
pre[fx]=fy;
return true;
}
return false;
}
void mintree()
{
int cnt=0;
for(int i=1;i<=m;i++)
{
if(join(map[i].s,map[i].e))
{
cnt++;
}
if(cnt==n-1)
{
maxn=map[i].w;
return;
}
}
}
long long int maxtree()
{
long long int cnt=0,sum=0;
for(int i=1;i<=m;i++)
{
if(maxn>=map[i].w&&join(map[i].s,map[i].e))
{//搞了好久才发现把join放前面是不行的
cnt++;
sum+=map[i].w;
}
if(cnt==n-1)
{
return sum;
}
}
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
init();
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&map[i].s,&map[i].e,&map[i].w);
}
sort(map+1,map+1+m,cmp);
mintree();
init();
sort(map+1,map+1+m,cmp1);
printf("%lld\n",maxtree());
}
}