逐个击破
题意
现在有N个城市,其中K个被敌方军团占领了,N个城市间有N-1条公路相连,破坏其中某条公路的代价是已知的,现在,告诉你K个敌方军团所在的城市,以及所有公路破坏的代价,请你算出花费最少的代价将这K个地方军团互相隔离开,以便第二步逐个击破敌人。
题解
我们加一个辅助数组记录每个城市是否被占领,然后跑最大生成树.当且仅当两个城市所在的连通块都被占领时,我们不取这条边,其余时候将当前两个城市的占领属性合并,最后 $ans$=用总代价-最大生成树权值和
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=1e5+10;
int n,k,fa[maxn];
ll ans;
bool ee[maxn];
struct fy
{
int from,to,d;
bool operator<(const fy&a)
const{return d>a.d;};
}q[maxn];
int find(int a)
{
while(a!=fa[a])a=fa[a]=fa[fa[a]];
return a;
}
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=k;i++)
{
int a;
scanf("%d",&a);
ee[a]=true;
}
for(int i=1;i<=n;i++)fa[i]=i;
for(int i=1;i<n;i++)
{
scanf("%d%d%d",&q[i].from,&q[i].to,&q[i].d);
ans+=q[i].d;
}
sort(q+1,q+n);
for(int i=1;i<n;i++)
{
int a=find(q[i].from);
int b=find(q[i].to);
if(ee[a]&&ee[b])continue;
fa[a]=b;
ee[a]|=ee[b];ee[b]|=ee[a];//合并属性
ans-=q[i].d;
}
printf("%lld\n",ans);
return 0;
}