题意
给定一棵树和根节点,每条边有边权。删去一些边,使得根节点和叶子节点不连通,求删的边的边权和最小值。
分析
树形dp。
令 表示
不与子树中的叶子节点相连的最小值。
考虑 的每一个儿子
和边权
显然断 中叶子节点的最优值为
然后 即可。
代码如下
#include <bits/stdc++.h>
#include<ext/pb_ds/hash_policy.hpp>
#include<ext/pb_ds/assoc_container.hpp>
#define N 100005
using namespace __gnu_pbds;
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
struct custom_hash {
static uint64_t splitmix64(uint64_t x) {
x += 0x9e3779b97f4a7c15;
x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
return x ^ (x >> 31);
}
size_t operator()(uint64_t x) const {
static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
return splitmix64(x + FIXED_RANDOM);
}
};
LL z = 1;
LL read(){
LL x, f = 1;
char ch;
while(ch = getchar(), ch < '0' || ch > '9') if(ch == '-') f = -1;
x = ch - '0';
while(ch = getchar(), ch >= '0' && ch <= '9') x = x * 10 + ch - 48;
return x * f;
}
int ksm(int a, int b, int p){
int s = 1;
while(b){
if(b & 1) s = z * s * a % p;
a = z * a * a % p;
b >>= 1;
}
return s;
}
struct node{
int a, b, n;
LL c;
}d[N * 2];
int cnt, h[N], a[N], fa[N];
LL f[N];
void cr(int a, int b, LL c){
d[++cnt].a = a; d[cnt].b = b; d[cnt].c = c; d[cnt].n = h[a]; h[a] = cnt;
}
void dfs(int a){
int i, b;
LL c, s = 0, zhi = 0;
f[a] = (z << 40);
for(i = h[a]; i; i = d[i].n){
b = d[i].b;
c = d[i].c;
if(b == fa[a]) continue;
zhi = 1;
fa[b] = a;
dfs(b);
s += min(c, f[b]);
}
if(zhi == 1) f[a] = s;
}
int main(){
int i, j, n, m, s, a, b, c;
n = read(); m = read(); s = read();
for(i = 1; i <= m; i++){
a = read(); b = read(); c = read();
cr(a, b, c);
cr(b, a, c);
}
dfs(s);
printf("%lld", f[s]);
return 0;
}

京公网安备 11010502036488号