逐个击破

题目

大意是,给定一棵树,有边权,其中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;
} 
posted @ 2025-05-04 16:02  归游  阅读(6)  评论(0)    收藏  举报