描述
三大战役的平津战场上,傅作义集团在以北平、天津为中心,东起唐山西至张家口的铁路线上摆起子一字长蛇阵,并企图在溃败时从海上南逃或向西逃窜。为了就地歼敌不让其逃走,mzd制定了先切断敌人东洒两头退路然后再逐个歼灭敌人的战略方针。
秉承伟大军事家的战略思想,作为一个有智慧的军长你,遇到了一个类似的战场局面:
现在有N个城市,其中K个被敌方军团占领了,N个城市间有N-1条公路相连,破坏其中某条公路的代价是已知的,现在,告诉你K个敌方军团所在的城市,以及所有公路破坏的代价,请你算出花费最少的代价将这K个地方军团互相隔离开,以便第二步逐个击破敌人。
输入格式
第一行包含两个正整数n和k。
第二行包含k个整数,表示哪个城市别敌军占领。
接下来n-1行,每行包含三个正整数a,b,c,表示从a城市到b城市有一条公路,以及破坏的代价c。
城市的编号从0开始计数。
其中:
2<=n<=100000
2<=k<=n
1<=c<=1000000
输出格式
包含一个整数,表示最少花费的代价。
测试样例1
输入
3 3
0 1 2
0 1 1
1 2 2
输出
3
测试样例2
输入
5 3
1 2 4
1 0 4
1 3 8
2 1 1
2 4 3
输出
4
思路:
破坏的最少=留下的最多,最大生成树,使最多一个敌军驻地包含在内
代码:
#include<iostream> #include<algorithm> #define mx 100005 using namespace std; struct edge{ int u; int v; long long w; }; int n,k,j[mx],vis[mx],pre[mx],fa,fb; edge g[mx],tmp; int findf(int x){ int t = x,k,r,sign = 0; while(x != pre[x]) x = pre[x]; r = x; if(j[r]) sign = 1; while(t != r){ j[t] = sign; k = pre[t]; pre[t] = r; t = k; } return r; } bool cmp(edge a,edge b){ return a.w > b.w; } int main(){ cin>>n>>k; long long u,v,w,ans = 0,sum = 0; for(int i = 1;i <= k;i++){ cin>>u; j[u] = 1; } for(int i = 1;i < n;i++){ cin>>u>>v>>w; sum += w; tmp.u = u; tmp.v = v; tmp.w = w; g[i] = tmp; } for(int i = 0;i <= n;i++){ pre[i] = i; } sort(g+1,g+n-1,cmp); for(int i = 1;i < n;i++){ fa = findf(g[i].u); fb = findf(g[i].v); if(j[fa] && j[fb]) continue; j[fb] = (j[fa] || j[fb]); pre[fa] = pre[fb]; ans += g[i].w; } cout<<sum - ans<<endl; return 0; }