1. 程式人生 > >2018年10月17日提高組 T1 平津戰役

2018年10月17日提高組 T1 平津戰役

大意

給定nn個節點,現在要刪除總代價最小的邊使得指定的mm個點兩兩不連通

思路

不考慮拆邊,考慮建邊

因為我們要使刪除總代價儘量少,也就是保留的邊儘量大,也就是生成樹,排序+並查集即可

程式碼

#include<cstdio>
#include<algorithm>
#define N 100001
using namespace std;long long ans;
int n,k,f[N],a,b;
bool vis[N];
inline int fa(register int x){return x==f[x]?x:f[x]=fa(f[x]);}//並查集
struct
node{int from,to,w;}e[N]; inline bool cmp(node x,node y){return x.w>y.w;} inline int read()//快讀 { char c;int d=1,f=0; while(c=getchar(),c<48||c>57)if(c=='-')d=-1;f=(f<<3)+(f<<1)+c-48; while(c=getchar(),c>47&&c<58)f=(f<<3)+(f<<1)+c-48; return d*f; } signed
main() { n=read();k=read();f[n]=n; for(register int i=1;i<=k;i++) vis[read()]=1; for(register int i=1;i<n;i++) e[i]=(node){read(),read(),read()},f[i]=i,ans+=e[i].w; sort(e+1,e+n,cmp); for(register int i=1;i<n;i++) { a=fa(e[i].from);b=fa(e[i].to); if(vis[a]&vis[b]) continue;//若在此之前已經連線了則不管它
f[a]=f[b]; ans-=e[i].w; vis[a]=vis[b]=vis[a]|vis[b];//連線 } printf("%lld",ans); }