HDU 3848 CC On The Tree 树形DP
题意:
给出一棵边带权的树,求距离最近的一对叶子。
分析:
通过DFS计算出\(min(u)\):以\(u\)为根的子树中最近叶子到\(u\)的距离。
然后维护一个前面子树\(v_i\)中叶子到\(u\)距离的最小值,就可以用这个最小值+当前子树中叶子到\(u\)的最短距离来更新答案。
如果根节点也是叶子节点的话,再用\(min(root)\)更新一下答案。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 10000 + 10;
const int INF = 0x3f3f3f3f;
struct Edge
{
int v, w, nxt;
Edge() {}
Edge(int v, int w, int nxt): v(v), w(w), nxt(nxt) {}
};
int ecnt, head[maxn];
Edge edges[maxn * 2];
void AddEdge(int u, int v, int w) {
edges[ecnt] = Edge(v, w, head[u]); head[u] = ecnt++;
edges[ecnt] = Edge(u, w, head[v]); head[v] = ecnt++;
}
int n;
int ans;
int minv[maxn];
int child[maxn];
void dfs(int u, int p) {
minv[u] = INF;
int minp = INF;
child[u] = 0;
for(int i = head[u]; ~i; i = edges[i].nxt) {
int v = edges[i].v;
if(v == p) continue;
child[u]++;
int w = edges[i].w;
dfs(v, u);
minv[u] = min(minv[u], minv[v] + w);
ans = min(ans, minp + minv[v] + w);
minp = min(minp, minv[v] + w);
}
if(!child[u]) minv[u] = 0;
}
int main()
{
while(scanf("%d", &n) == 1 && n) {
ecnt = 0;
memset(head, -1, sizeof(head));
for(int i = 1; i < n; i++) {
int u, v, w; scanf("%d%d%d", &u, &v, &w);
AddEdge(u, v, w);
}
ans = INF;
dfs(1, 0);
if(child[1] == 1) ans = min(ans, minv[1]);
printf("%d\n", ans);
}
return 0;
}