[BZOJ 1907] 树的路径覆盖 【树形DP】
2015-04-14 16:16
99 查看
题目链接:BZOJ - 1907
f[x][1] 表示以 x 为根的子树可以与 x 的父亲连接的最小路径数。
转移的方式非常巧妙,Orz PoPoQQQ 的 blog 。
题目分析
使用树形 DP,f[x][0] 表示以 x 为根的子树不能与 x 的父亲连接的最小路径数(即 x 是一个折线的拐点)。f[x][1] 表示以 x 为根的子树可以与 x 的父亲连接的最小路径数。
转移的方式非常巧妙,Orz PoPoQQQ 的 blog 。
代码
#include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> using namespace std; const int MaxN = 10000 + 5; int T, n; int f[MaxN][2]; struct Edge { int v; Edge *Next; } E[MaxN * 2], *P = E, *Point[MaxN]; inline void AddEdge(int x, int y) { ++P; P -> v = y; P -> Next = Point[x]; Point[x] = P; } inline int gmin(int a, int b) {return a < b ? a : b;} void Solve(int x, int Fa) { f[x][0] = f[x][1] = 1; int Temp = 0; for (Edge *j = Point[x]; j; j = j -> Next) { if (j -> v == Fa) continue; Solve(j -> v, x); f[x][0] = gmin(f[x][0] + f[j -> v][0], f[x][1] + f[j -> v][1] - 1); f[x][1] = gmin(f[x][1] + f[j -> v][0], Temp + f[j -> v][1]); Temp += f[j -> v][0]; } } int main() { scanf("%d", &T); for (int Case = 1; Case <= T; ++Case) { memset(E, 0, sizeof(E)); P = E; memset(Point, 0, sizeof(Point)); scanf("%d", &n); int a, b; for (int i = 1; i <= n - 1; ++i) { scanf("%d%d", &a, &b); AddEdge(a, b); AddEdge(b, a); } Solve(1, 0); printf("%d\n", f[1][0]); } return 0; }
相关文章推荐
- BZOJ 1907 树的路径覆盖 - 树形DP/贪心
- BZOJ1907: 树的路径覆盖 树形DP
- 【bzoj1907】树的路径覆盖 树形dp
- [BZOJ1907]-树的最小路径覆盖-树形DP||贪心
- [树形DP || 贪心] BZOJ 1907 树的路径覆盖
- BZOJ 1907 树的路径覆盖 树形DP
- bzoj 1907: 树的路径覆盖 (贪心+dfs+树形dp)
- bzoj 1907: 树的路径覆盖【贪心+树形dp】
- [BZOJ1907]树的路径覆盖(贪心||树形dp)
- bzoj1907: 树的路径覆盖(树形DP)
- 【BZOJ1907】树的路径覆盖【贪心】
- bzoj 1907(树形dp)
- BZOJ 1907: 树的路径覆盖|贪心
- 【bzoj1907】树的路径覆盖
- bzoj 1907: 树的路径覆盖
- BZOJ1907 树的路径覆盖
- BZOJ 1907 树的路径覆盖
- [BZOJ1907]树的路径覆盖(贪心)
- BZOJ 1907: 树的路径覆盖 树型dp
- 【BZOJ1907】树的路径覆盖