您的位置:首页 > 其它

bzoj 1907(树形dp)

2017-09-03 16:00 387 查看
传送门

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  树形dp