正题
题目大意
一棵树n个点
有k个点被占领,删除每一条边都有不同的代价,然后要求所以被占领的点相互隔开,代价最小。
解题思路
我们可以考虑反构图,将边权排序,然后对于每条边,如果加入这条边后不会使敌军连接就加这条边,然后加入,然后用并查集判断敌军是否连接。
code
#include<cstdio>
#include<algorithm>
#define N 100010
using namespace std;
struct node{int x,y,w;
}a[N];
int n,k,tot,father[N];
long long ans;
bool army[N];
int find(int x)//找祖先
{return father[x]==x?x:father[x]=find(father[x]);
}
bool cmp(node x,node y)
{return x.w>y.w;}
int main()
{scanf("%d%d",&n,&k);for(int i=1;i<=k;i++){scanf("%d",&tot);tot++;army[tot]=true;}for(int i=1;i<n;i++){father[i]=i;scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].w);a[i].x++;a[i].y++;ans+=a[i].w;}father[n]=n;sort(a+1,a+n,cmp);for(int i=1;i<n;i++){int fa=find(a[i].x),fb=find(a[i].y);if(army[fa]&&army[fb]) continue;//会使军队连接ans-=a[i].w;father[fa]=father[fb];//连接army[fa]=army[fb]=army[fa]|army[fb];//计算军队}printf("%lld",ans);
}