Tyvj 3737 逐个击破
描述
三大战役的平津战场上,傅作义集团在以北平、天津为中心,东起唐山西至张家口的铁路线上摆起子一字长蛇阵,并企图在溃败时从海上南逃或向西逃窜。为了就地歼敌不让其逃走,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
思路:
破坏的最少=留下的最多,最大生成树,使最多一个敌军驻地包含在内
代码:
1 #include<iostream> 2 #include<algorithm> 3 #define mx 100005 4 using namespace std; 5 struct edge{ 6 int u; 7 int v; 8 long long w; 9 }; 10 int n,k,j[mx],vis[mx],pre[mx],fa,fb; 11 edge g[mx],tmp; 12 int findf(int x){ 13 int t = x,k,r,sign = 0; 14 while(x != pre[x]) x = pre[x]; 15 r = x; 16 if(j[r]) sign = 1; 17 while(t != r){ 18 j[t] = sign; 19 k = pre[t]; 20 pre[t] = r; 21 t = k; 22 } 23 return r; 24 } 25 bool cmp(edge a,edge b){ 26 return a.w > b.w; 27 } 28 int main(){ 29 cin>>n>>k; 30 long long u,v,w,ans = 0,sum = 0; 31 for(int i = 1;i <= k;i++){ 32 cin>>u; 33 j[u] = 1; 34 } 35 for(int i = 1;i < n;i++){ 36 cin>>u>>v>>w; 37 sum += w; 38 tmp.u = u; 39 tmp.v = v; 40 tmp.w = w; 41 g[i] = tmp; 42 } 43 for(int i = 0;i <= n;i++){ 44 pre[i] = i; 45 } 46 sort(g+1,g+n-1,cmp); 47 48 49 for(int i = 1;i < n;i++){ 50 fa = findf(g[i].u); 51 fb = findf(g[i].v); 52 if(j[fa] && j[fb]) continue; 53 j[fb] = (j[fa] || j[fb]); 54 pre[fa] = pre[fb]; 55 ans += g[i].w; 56 57 } 58 cout<<sum - ans<<endl; 59 return 0; 60 }
时间: 2024-10-14 01:27:33