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

posted @ 2025-03-07 11:26  WHUStar  阅读(15)  评论(0)    收藏  举报