vijos1144&&bzoj1596(树形dp,树上最小控制集
2016-08-22 10:15
411 查看
非常经典,但是关于转移方程不重不漏的证明还是需要自己证一下
f【i】【0】表示选根节点的最小费用
f【i】【1】表示选根的父亲的最小费用
f【i】【2】表示选根的儿子的最小费用
f【i】【0】和f【i】【2】这两个状态比较好想,
那么如何考虑出f【i】【1】选父亲这个状态呢?实际上,当我们只有另外两个状态的时候,会出现一些情况无法约束。那么,我们就多一种表示状态,来进行约束。
为什么选这一种?求人来帮帮我。。。
转移推一下就好了,这种状态表示的方法极为巧妙,树形dp中设计状态真心值得思考
bzoj1596#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
int n;
int head[10005],to[10005*5],pre[10005*5],tot;
void addedge(int x,int y)
{
to[++tot]=y;pre[tot]=head[x];head[x]=tot;
}
int f[10050][3];
void dfs(int u,int fa)
{
f[u][0]=1;
f[u][1]=0;
f[u][2]=0;
int t=inf;
for (int i=head[u];i;i=pre[i])
if (to[i]!=fa)
{
int v=to[i];
dfs(v,u);
f[u][0]+=min(f[v][0],f[v][1]);
f[u][1]+=min(f[v][0],f[v][2]);
f[u][2]+=min(f[v][0],f[v][2]);
t=min(t,f[v][0]-f[v][2]);
}
f[u][2]+=max(t,0);
}
int main()
{
scanf("%d",&n);
int x,y;
for (int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
addedge(x,y);
addedge(y,x);
}
dfs(1,0);
printf("%d",min(f[1][0],f[1][2]));
return 0;
}
f【i】【0】表示选根节点的最小费用
f【i】【1】表示选根的父亲的最小费用
f【i】【2】表示选根的儿子的最小费用
f【i】【0】和f【i】【2】这两个状态比较好想,
那么如何考虑出f【i】【1】选父亲这个状态呢?实际上,当我们只有另外两个状态的时候,会出现一些情况无法约束。那么,我们就多一种表示状态,来进行约束。
为什么选这一种?求人来帮帮我。。。
转移推一下就好了,这种状态表示的方法极为巧妙,树形dp中设计状态真心值得思考
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> using namespace std; const int inf=0x3f3f3f3f; int n,rt,cost[1505]; int head[1505],to[5000],pre[5000],tot; void addedge(int x,int y) { to[++tot]=y;pre[tot]=head[x];head[x]=tot; } bool b[1505]; int dp[1505][3]; void dfs(int u) { dp[u][0]=cost[u];//1:father 2:son 0:now dp[u][1]=0; dp[u][2]=0; int t=inf; for (int i=head[u];i;i=pre[i]) { int v=to[i]; dfs(v); dp[u][0]+=min(dp[v][0],dp[v][1]); dp[u][1]+=min(dp[v][0],dp[v][2]); dp[u][2]+=min(dp[v][0],dp[v][2]); t=min(t,dp[v][0]-dp[v][2]); } dp[u][2]+=max(t,0); } int main() { scanf("%d",&n); int x,t,y; for (int i=1;i<=n;i++) { scanf("%d",&x); scanf("%d%d",&cost[x],&t); for (int j=1;j<=t;j++) { scanf("%d",&y); addedge(x,y); b[y]=true; } } for (int i=1;i<=n;i++) if (!b[i]) rt=i; dfs(rt); printf("%d",min(dp[rt][0],dp[rt][2])); return 0; }
bzoj1596#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
int n;
int head[10005],to[10005*5],pre[10005*5],tot;
void addedge(int x,int y)
{
to[++tot]=y;pre[tot]=head[x];head[x]=tot;
}
int f[10050][3];
void dfs(int u,int fa)
{
f[u][0]=1;
f[u][1]=0;
f[u][2]=0;
int t=inf;
for (int i=head[u];i;i=pre[i])
if (to[i]!=fa)
{
int v=to[i];
dfs(v,u);
f[u][0]+=min(f[v][0],f[v][1]);
f[u][1]+=min(f[v][0],f[v][2]);
f[u][2]+=min(f[v][0],f[v][2]);
t=min(t,f[v][0]-f[v][2]);
}
f[u][2]+=max(t,0);
}
int main()
{
scanf("%d",&n);
int x,y;
for (int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
addedge(x,y);
addedge(y,x);
}
dfs(1,0);
printf("%d",min(f[1][0],f[1][2]));
return 0;
}
相关文章推荐
- poj 3659 树形dp(树上的最小支配集)
- hdu 4003 Find Metal Mineral K个机器人从S出发遍历树上所有点的经过的最小权值 树形DP
- Bzoj2260 商店购物 & 4349 最小树形图
- [DP 匈牙利 最小链覆盖] BZOJ 2044 三维导弹拦截 & 计蒜客 271 拦截导弹
- bzoj2260: 商店购物 && 4349: 最小树形图
- [BZOJ1596][Usaco2008 Jan]电话网络(贪心||树形dp)
- 【Bzoj2260】【Bzoj4349】商店购物 & 最小树形图
- hdu4126 Genghis Khan the Conqueror--最小生成树 & 树形DP(待解决)
- 【bzoj4033】树上染色 树形dp
- 【bzoj1596】[Usaco2008 Jan]电话网络 树形dp
- bzoj 1917: [Ctsc2010]星际旅行 树形dp解决树上网络流
- BZOJ(本校) 3049 第K大 - 二分&树形dp
- bzoj 2260&&4349 最小树形图
- UVA1292-----Strategic game-----树形DP解决树上的最小点覆盖问题
- bzoj2286 消耗战 虚树&树形dp
- BZOJ 2260 商店购物 & 4349 最小树形图
- bzoj4242 水壶 最小生成树&树上倍增
- 【BZOJ 2260&&4349】最小树形图&&商店购物 朱刘算法
- 【树形DP】BZOJ1596-[Usaco2008 Jan]电话网络
- [第二类斯特林数 树形DP] HDU 4625 JZPTREE && BZOJ 2159 Crash 的文明世界