您的位置:首页 > 其它

树形DP <简单树形DP 对我来说重点在建树> hlg 1474

2012-07-19 22:56 411 查看
受挫了..

主要是题做的还太少了..而且我基础不踏实..建树都建不好..

加油吧~

题意:

给出 n 个节点和 m 个关系..

保证是一棵树..父子节点不能同时出现..根节点一定要有..求节点出现最多值..

思路:

叶节点的值是可以肯定的..从下往上DP就好..

对我来说难点还是不会建树..

Tips:

初始条件: dp[ leaf ][ 0 ] = 0, dp[ leaf ][ 1 ] = 1;

动态转移方程 :

dp[r][1] += dp[tmp][0];

dp[r][0] += max(dp[tmp][1], dp[tmp][0]);

结果: dp[ root ][1]

L_Squirrel:

用vector 方便建树..

用visited来标记..然后遍历可以找到根节点..

Code:

#include <stdio.h>
#include <cstring>
#include <fstream>
#include <vector>
using namespace std;

vector<int> con[2010];
bool visited[2010];
int dp[2010][2];

void dfs(int r)
{
dp[r][0] = 0;
dp[r][1] = 1;
int len = con[r].size();
for(int i = 0; i < len; ++i){
int tmp = con[r][i];
dfs(tmp);
dp[r][1] += dp[tmp][0];
dp[r][0] += max(dp[tmp][1], dp[tmp][0]);
}
}

int main()
{
int i, j, k;
int n, m;
int a, b;
//  freopen("e:\\acm\\mess\\stdin-stdout\\in_c.txt", "r", stdin);
//  freopen("e:\\acm\\mess\\stdin-stdout\\out_c.txt", "w", stdout);
while(scanf("%d %d", &n, &m) != EOF)
{
memset(visited, false, sizeof(visited));
memset(dp, 0, sizeof(dp));
for(i = 0; i <= n; ++i)
con[i].clear();

for(i = 1; i <= m; ++i){
scanf("%d %d", &a, &b);
con[a].push_back(b);
visited[b] = true;
}
for(i = 1; i <= n; ++i)
if(!visited[i]) break;
int root = i;

dfs(root);

printf("%d\n", dp[root][1]);
}
return 0;
}


链表建树:

struct node

{

int v,next;

}edge[ ];

void add(int u,int v)

{

edge[tol].v=v;

edge[tol].next=head[u];

head[u]=tol++;

}

void dfs(int x)

{

dp[x][1]=1;

dp[x][0]=0;

for(int i=head[x];i!=-1;i=edge[i].next)

{

int t=edge[i].v;

dfs(t);

dp[x][0]+=max(dp[t][1],dp[t][0]);

dp[x][1]+=dp[t][0];

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: