您的位置:首页 > 其它

树形dp总结

2016-08-21 22:39 218 查看
这个月一直搞dp了,状压,数位,树形,感觉虽然有时训练很辛苦,但真的很充实。

这个星期看了一些树形dp的资料。

树形dp简单来说就是在树上的dp,这里的很多题,都和背包有联系,从一个根节点开始,分配方案给它的子树。

有一个很有意思的题。没有上司的聚会(HDU 1520)。

大致题意就是说,要举办一个聚会,每个人都有一个权值,然后所有人都不希望碰到自己的直系上司。显然没有成环的现象。

那么这些人的关系就可以组成一个树。典型的树形dp。

一个人无非2个状态,来或者不来。

那么我们就可以建一个dp[i][j],代表第i个来或者不来的最大权值。j=0不来,j=1来。

在用DFS搜索一遍就好了。

下面附上代码。

#include<bits/stdc++.h>
using namespace std;
int val[6005],dp[6005][3];
int n;
bool vis[6005];
vector<int> v[6005];
void dfs(int a)
{
vis[a]=1;
dp[a][1]=val[a];
dp[a][0]=0;
int i,j,k;
for(i=0;i<v[a].size();i++)
{
int w=v[a][i];
if(vis[w])
continue;
dfs(w);
dp[a][0]+=max(dp[w][1],dp[w][0]);
dp[a][1]+=dp[w][0];
}
}
int main()
{
int i,j,k;
while(~scanf("%d",&n))
{
memset(vis,0,sizeof(vis));
memset(dp,0,sizeof(dp));
for(i=1;i<=n;i++)
{
scanf("%d",&val[i]);
v[i].clear();
}
int a,b;
while(scanf("%d%d",&a,&b) && a+b)
{
v[a].push_back(b);
v[b].push_back(a);
}
dfs(1);
printf("%d\n",max(dp[1][0],dp[1][1]));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dp