P3931 SAC E#1 - 一道难题 Tree
链接
https://www.luogu.com.cn/problem/P3931
思路
树形dp。思路简单:使用dp[x]记录删掉以x为根节点的子树 包含的所有叶子节点 所需的最小代价,那么dp[x] +=min(dp[son],cost[x][son])。还有要注意的点就是不能直接用cost存,最好用vector存边(见代码)。以及可以用dfs序重编号。
代码
#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define int long long
const int N = 1e5 + 10;
const int M = 10007;
int n;
struct Edge {
int to, val;
Edge(){}
Edge(int t,int v) {
to = t; val = v;
}
};
vector<Edge>nxt[N];
int idx[N];
int idy[N];
int dp[N];
int cnt = 1;
void dfs(int fa,int u)
{
bool isleaf = true;
for (Edge x : nxt[u])
{
if (x.to == fa)continue;
dfs(u, x.to);
isleaf = false;
}
idy[cnt] = u;
idx[u] = cnt++;
if (isleaf)dp[idx[u]] = LLONG_MAX;
}
void cal(int x)
{
if (dp[x] == LLONG_MAX)return;
for (Edge ea : nxt[idy[x]])
{
dp[x] += min(ea.val, dp[idx[ea.to]]);
}
}
signed main()
{
IOS;
cin >> n;
int root; cin >> root;
for (int i = 1; i < n; i++)
{
int u, v, c;
cin >> u >> v >> c;
nxt[u].push_back(Edge(v, c));
nxt[v].push_back(Edge(u, c));
}
dfs(0, root);
for (int i = 1; i <= n; i++)
cal(i);
cout << dp[n];
return 0;
}

浙公网安备 33010602011771号