先把原图里本来就连在一起的点分成几团,每一团只记住团内最大的点权。
接下来要把这些团连成一个大团,最省钱的做法就是让最大点权那一团当中心,把其他团一个个接过来。这样总花费就是所有团最大点权加起来,再减去最大的那个。
void solve(){
int n,m;cin>>n>>m;
vi a(n+1);
for(int i=1;i<=n;++i)cin>>a[i];
vi fa(n+1),sz(n+1,1);
for(int i=1;i<=n;++i)fa[i]=i;
auto fd=[&](auto &&self,int x)->int{
if(fa[x]==x)return x;
return fa[x]=self(self,fa[x]);
};
auto mg=[&](int x,int y){
x=fd(fd,x),y=fd(fd,y);
if(x==y)return;
if(sz[x]<sz[y])swap(x,y);
fa[y]=x;
sz[x]+=sz[y];
};
for(int i=1;i<=m;++i){
int u,v;cin>>u>>v;
mg(u,v);
}
vll mx(n+1,0),b;
for(int i=1;i<=n;++i){
int r=fd(fd,i);
mx[r]=max(mx[r],(ll)a[i]);
}
for(int i=1;i<=n;++i){
if(fd(fd,i)==i)b.push_back(mx[i]);
}
sort(all(b));
ll ans=0;
for(int i=1;i<(int)b.size();++i)ans+=b[i];
cout<<ans<<endl;
}

京公网安备 11010502036488号