版权声明:请大家斧正,如喜欢的话,为拙见点一个赞吧。 https://blog.csdn.net/qq_39897867/article/details/83214886
题目
https://www.luogu.org/problemnew/show/P2700
解题思路
这道题可以逆向思考,把断边变成建边。要求删掉最少的边,那肯定是构较大的边,先从大到小排一个序,再用并查集判断一下两点是否同一联通块。
代码
#include<cstdio>
#include<algorithm>
#define rr register
using namespace std;
struct node{int x,y,z;}a[100010];
int n,k,f[100010];
long long ans;
bool b[100010];
bool cmp(node x,node y){return x.z>y.z; }
inline int found(int x) { return f[x]==x?f[x]:f[x]=found(f[x]);}
inline int read()
{
int p=0,f=1; char c=getchar();
while (c<'0'||c>'9') { if (c=='-') f=-1; c=getchar(); }
while (c>='0'&&c<='9') p=(p<<3)+(p<<1)+c-'0',c=getchar();
return p*f;
}
int main()
{
n=read(); k=read(); f[n]=n;
for (rr int i=1;i<=k;i++) b[read()]=true;
for (rr int i=1;i<n;f[i]=i,i++)
a[i]=(node){read(),read(),read()},ans+=(long long)a[i].z;
sort(a+1,a+n,cmp);
for (rr int i=1;i<n;i++)
{
int x=found(a[i].x),y=found(a[i].y),z=a[i].z;
if (b[x]&&b[y]) continue;
f[x]=f[y]; ans-=(long long)z;
if (b[x]) b[y]=true;
else if (b[y]) b[x]=true;
}
printf("%lld",ans);
}