zoukankan      html  css  js  c++  java
  • 图论——生成树

    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 }
    View Code
     
     
  • 相关阅读:
    【POJ 1958】 Strange Towers of Hanoi
    【HNOI 2003】 激光炸弹
    【POJ 3263】 Tallest Cow
    【POJ 2689】 Prime Distance
    【POJ 2777】 Count Color
    【POJ 1995】 Raising Modulo Numbers
    【POJ 1845】 Sumdiv
    6月16日省中集训题解
    【TJOI 2018】数学计算
    【POJ 1275】 Cashier Employment
  • 原文地址:https://www.cnblogs.com/hyfer/p/4841805.html
Copyright © 2011-2022 走看看