2017年09月07日提高组第一式 A

来源:互联网 发布:mysql 生成时间序列 编辑:程序博客网 时间:2024/05/18 17:44

Description


三大战役的平津战场上,傅作义集团在以北平、天津为中心,东起唐山西至张家口的铁路线上摆起子一字长蛇阵,并企图在溃败时从海上南逃或向西逃窜。为了就地歼敌不让其逃走,毛泽东制定了先切断敌人东洒两头退路然后再逐个歼灭敌人的战略方针。
秉承伟大军事家的战略思想,作为一个有智慧的军长你,遇到了一个类似的战场局面:
现在有N个城市,其中K个被敌方军团占领了,N个城市间有N-1条公路相连,破坏其中某条公路的代价是已知的,现在,告诉你K个敌方军团所在的城市,以及所有公路破坏的代价,请你算出花费最少的代价将这K个地方军团互相隔离开,以便第二步逐个击破敌人。

Input


第一行包含两个正整数n和k。
第二行包含k个整数,表示哪个城市别敌军占领。
接下来n-1行,每行包含三个正整数a,b,c,表示从a城市到b城市有一条公路,以及破坏的代价c。
城市的编号从0开始计数。

Output


包含一个整数,表示最少花费的代价。

Hint


数据范围
2<=n<=100000
2<=k<=n
1<=c<=1000000

Source


2014年广东省青少年信息学竞赛中山市选拔赛

Solution


水题,按照费用降序排序边,并查集维护一个边集合是否存在军队,每次合并两个不同时存在军队的集合就可以了

Code


#include <stdio.h>#include <algorithm>#define rep(i, st, ed) for (int i = st; i <= ed; i += 1)#define ll long long#define N 200001int fa[N], tx[N], ty[N], tw[N], rank[N], g[N];inline int read() {    int x = 0; char ch = getchar();    for (; ch<'0'||ch>'9'; ch = getchar());    for (; ch<='9'&&ch>='0'; ((x*=10)+=ch-'0'), ch = getchar());    return x;}inline int getFather(int now) {    if (fa[now] == now) {        return now;    }    return fa[now] = getFather(fa[now]);}inline bool merge(int x, int y) {    int fx = getFather(x);    int fy = getFather(y);    if (fx == fy || g[fx] == 1 && g[fy] == 1) {        return 0;    }    fa[fx] = fy;    g[fy] |= g[fx];    return 1;}inline bool cmp(int a, int b) {    return tw[a] > tw[b];}int main(void) {    int n = read();    int k = read();    rep(i, 1, k) {        int x = read();        g[x] = 1;    }    ll ans = 0;    rep(i, 1, n - 1) {        tx[i] = read();        ty[i] = read();        ans += tw[i] = read();        rank[i] = fa[i] = i;    }    std:: sort(rank + 1, rank + n, cmp);    rep(i, 1, n - 1) {        if (merge(tx[rank[i]], ty[rank[i]])) {            ans -= tw[rank[i]];        }    }    printf("%lld\n", ans);    return 0;}
原创粉丝点击