受挫了..
主要是题做的还太少了..而且我基础不踏实..建树都建不好..
加油吧~
题意:
给出 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];
}
}