逐个击破
题目
大意是,给定一棵树,有边权,其中k个点之间不能连通,拆除某些边,以达成目标,求最小值.
正难则反,逆向思维
我们可以尝试建图,在建图的时候使得这些点不得连通
建图时,与其k个点直接或间接相连的点也不能与,这k个点相连,这样保证了k个点互不连通
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n,k;
const int maxn=2e5+10;
int f[maxn];
bool book[maxn];
struct node{
int u,v,w;
}e[maxn];
long long ans=0;
bool cmp(node a,node b){
return a.w>b.w;
}
int find(int x){
if(x!=f[x]) return f[x]=find(f[x]);
return x;
}
int main(){
cin>>n>>k;
for(int i=1;i<=n;++i) f[i]=i;
for(int i=1;i<=k;++i){
int x;cin>>x;book[x]=1;
}
for(int i=1;i<n;++i){
int u,v,w;cin>>u>>v>>w;
e[i]={u,v,w};
ans+=w;
}
sort(e+1,e+n,cmp);
for(int i=1;i<n;++i){
auto t=e[i];
int fu=find(t.u),fv=find(t.v);
if(book[fu] and book [fv]) continue;//不能建此边
f[fu]=fv;
ans-=t.w;
if(book[fu]) book[fv]=1;//与k个点间接或直接相连的点打好标记,与这k个点连通
else if(book[fv]) book[fu]=1;
}
cout<<ans<<endl;
}

浙公网安备 33010602011771号