您的位置:首页 > 其它

luogu 2700 逐个击破

2017-10-31 17:10 246 查看

Description

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

Input

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

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

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

Output

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

Sample Input

5 3

1 2 4

1 0 4

1 3 8

2 1 1

2 4 3

Sample Output

4

Hint

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

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

Solution :

    我们可以转化一下,不是要使他们不连通吗,而且减去最小边,我们可以反过来想,建一片最大森林,原树的边权总和减去最大森林的和就是我们要的答案,写法和最大生成树一样,只是打个标记,我这里的是 vis。

Code :

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <ctime>
#include <map>
#include <vector>
#define LL long long
using namespace std;

inline int read() {
int i = 0, f = 1;
char ch = getchar();
while(!isdigit(ch)) {
if(ch == '-') f = -1; ch = getchar();
}
while(isdigit(ch)) {
i = (i << 3) + (i << 1) + ch - '0'; ch = getchar();
}
return i * f;
}

const int MAXN = 1e5 + 5;
int fa[MAXN], vis[MAXN];

struct point {
int from, to;
LL w;
inline bool operator < (const point & a) const {
return w > a.w;
}
};
point e[MAXN];

inline int getfather(int x) {
return fa[x] == x ? x : fa[x] = getfather(fa[x]);
}

int main() {
LL ans = 0;
int n = read(), k = read();
for(int i = 1; i <= n; ++i) fa[i] = i;
for(int i = 1; i <= k; ++i) vis[read() + 1] = 1;
for(int i = 1; i <= n - 1; ++i)
e[i].from = read() + 1, e[i].to = read() + 1, e[i].w = (LL)read(), ans += e[i].w;
sort(e + 1, e + n);
for(int i = 1; i <= n - 1; ++i) {
int gx = getfather(e[i].from);
int gy = getfather(e[i].to);
if(vis[gx] + vis[gy] == 2) continue;
if(gx == gy) continue;
int now = vis[gx] + vis[gy];
vis[gx] = now, vis[gy] = now;
fa[gx] = gy;
ans -= e[i].w;
}
cout<<ans<<'\n';
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  洛谷 最大生成树