bzoj 1907(树形dp)
2017-09-03 16:00
387 查看
传送门
dp数组定义在代码里有注释,转移方程要好好想想,反正我是想了半天,每枚举一个儿子,更新的dp值相当于是前缀dp值(只考虑了枚举过的儿子造成的贡献),对于每个点,枚举了它所有儿子后才得到了真正需要的dp值。明显看出dp转移时有点给人一种滚动数组的感觉。
可以去看看zyf2000大佬的博客
dp数组定义在代码里有注释,转移方程要好好想想,反正我是想了半天,每枚举一个儿子,更新的dp值相当于是前缀dp值(只考虑了枚举过的儿子造成的贡献),对于每个点,枚举了它所有儿子后才得到了真正需要的dp值。明显看出dp转移时有点给人一种滚动数组的感觉。
可以去看看zyf2000大佬的博客
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int MAXN=100004; int n; int head[MAXN],edge=0; struct EDGE { int v,nxt; }e[MAXN<<1]; int dp[MAXN][2];//0/1:过p的路径以p为终点/连向fa inline int read() { int x=0;char c=getchar(); while (c<'0'||c>'9') c=getchar(); while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); return x; } inline void adde(int u,int v) { e[edge].nxt=head[u],e[edge].v=v,head[u]=edge++; e[edge].nxt=head[v],e[edge].v=u,head[v]=edge++; } void dfs(int p,int fa) { dp[p][1]=dp[p][0]=1; int temp=0; for (int i=head[p];~i;i=e[i].nxt) { int v=e[i].v; if (v^fa) { dfs(v,p); dp[p][0]=min(dp[p][0]+dp[v][0],dp[p][1]+dp[v][1]-1); dp[p][1]=min(dp[p][1]+dp[v][0],temp+dp[v][1]); temp+=dp[v][0]; } } } int main() { // freopen("bzoj 1907.in","r",stdin); int kase=read(); while (kase--) { memset(head,-1,sizeof(head)); n=read(); for (int i=1;i<n;++i) { int u=read(),v=read(); adde(u,v); } dfs(1,0); printf("%d\n",min(dp[1][0],dp[1][1])); } return 0; }
相关文章推荐
- BZOJ1907: 树的路径覆盖 树形DP
- bzoj 1907: 树的路径覆盖 (贪心+dfs+树形dp)
- [BZOJ1907]树的路径覆盖(贪心||树形dp)
- BZOJ 1907 树的路径覆盖 - 树形DP/贪心
- bzoj 1907: 树的路径覆盖【贪心+树形dp】
- 【bzoj1907】树的路径覆盖 树形dp
- [BZOJ 1907] 树的路径覆盖 【树形DP】
- [BZOJ1907]-树的最小路径覆盖-树形DP||贪心
- [树形DP || 贪心] BZOJ 1907 树的路径覆盖
- BZOJ 1907 树的路径覆盖 树形DP
- [bzoj1063][Noi2008]道路设计【树形dp】
- 【BZOJ3238】差异(AHOI2013)-后缀自动机+树形DP
- BZOJ 2097 USACO 2010 Dec Gold Exercise 奶牛健美操 二分答案 树形DP 贪心
- [BZOJ1017][JSOI2008][树形DP]魔兽地图DotR
- bzoj2314: 士兵的放置(树形DP)
- BZOJ 3566: [SHOI2014]概率充电器 期望DP + 树形DP
- [bzoj3037/2068]创世纪[Poi2004]SZP_树形dp_并查集_基环树
- bzoj 4027 树形dp
- [bzoj4033][树形DP]树上染色
- BZOJ 2286: [Sdoi2011]消耗战 虚树 树形dp