【洛谷P2700】逐个击破

题目背景

三大战役的平津战场上,傅作义集团在以北平、天津为中心,东起唐山西至张家口的铁路线上摆起子一字长蛇阵,并企图在溃败时从海上南逃或向西逃窜。为了就地歼敌不让其逃走,(被和谐了)制定了先切断敌人东西两头退路然后再逐个歼灭敌人的战略方针。秉承伟大军事家的战略思想,作为一个有智慧的军长你,遇到了一个类似的战场局面。

题目描述

现在有N个城市,其中K个被敌方军团占领了,N个城市间有N-1条公路相连,破坏其中某条公路的代价是已知的,现在,告诉你K个敌方军团所在的城市,以及所有公路破坏的代价,请你算出花费最少的代价将这K个地方军团互相隔离开,以便第二步逐个击破敌人。

输入输出格式

输入格式:

第一行包含两个正整数n和k。

第二行包含k个整数,表示哪个城市别敌军占领。

接下来n-1行,每行包含三个正整数a,b,c,表示从a城市到b城市有一条公路,以及破坏的代价c。城市的编号从0开始。

输出格式:

输出一行一个整数,表示最少花费的代价。

说明

【数据范围】

10%的数据:2≤n≤10;

100%的数据:2≤n≤100000,2≤k≤n,1≤c≤1000000。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=100000+5;
template<class T>
inline void read(T &x){
    x=0;char ch=getchar();
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
}
int n,k,x,u,v,c; ll ans;
int father[maxn];
bool vis[maxn];
struct node{
    int x,y,c;
    bool operator < (const node &j) const {
        return c>j.c;
    }    
}e[maxn];
int find(int x){
    if(x!=father[x]) father[x]=find(father[x]);
    return father[x];
}
int main(){
    read(n);read(k);
    for(int i=1;i<=k;++i) read(x),vis[x]=1;
    for(int i=1;i<=n;++i) father[i]=i;
    for(int i=1;i<n;++i){
        read(e[i].x);read(e[i].y);read(e[i].c);
    }
    sort(e+1,e+n+1);
    for(int i=1;i<n;++i){
        int r1=find(e[i].x),r2=find(e[i].y);
        if(r1!=r2){
            if(vis[r1]&&vis[r2]) ans+=e[i].c;
            else if(vis[r1]&&!vis[r2]) father[r2]=r1;
            else if(!vis[r1]&&vis[r2]) father[r1]=r2;
            else father[r1]=r2;
        }
    }
    printf("%lld",ans);
    return 0;
}

 

posted @ 2017-10-28 22:33  沐灵_hh  阅读(178)  评论(0编辑  收藏  举报