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';
}