树形DP
hdu1520View Code
题意:给定一棵关系树,每个节点有个权值,子节点和父节点不能同时选,问最后能选的最大价值是多少?
点u有两个状态,选 - dp[u][1],不选 - dp[u][0]
设v为儿子结点,则状态转移方程为:
dp[u][1] = sum(dp[v][0]) 说明:父节点选后,儿子节点都不能选
dp[u][0] = sum( max(dp[v][0], dp[v][1]) ) 说明:父节点不选时,子节点可选可不选,取决于值的大小
从叶子节点开始往根节点遍历,因此用dfs,在回溯阶段更新。
/*
*
* 树形DP
*
*/
#include <iostream>
#include <cstring>
using namespace std;
#define N 6010
#define M 12010
int head[N], eNum;
struct Edge
{
int e, next;
}edge[M];
int dp[N][2], num[N];
int max(int x, int y)
{
return x > y ? x : y;
}
void AddEdge(int u, int v)
{
edge[eNum].e = v;
edge[eNum].next = head[u];
head[u] = eNum++;
}
void dfs(int u, int fa)
{
//if(vis[u]) return ;
//vis[u] = 1;
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].e;
if(v == fa) continue;
dfs(v, u);
dp[u][1] += dp[v][0];
dp[u][0] += max(dp[v][0], dp[v][1]);
}
dp[u][1] += num[u];
}
int main()
{
int n;
while(cin >> n)
{
for(int i=1; i<=n; i++)
cin >> num[i];
memset(dp,0,sizeof(dp));
memset(head,-1,sizeof(head));
//memset(vis,0,sizeof(vis));
eNum = 0;
int u, v;
while(cin >> u >> v)
{
if(u==0 && v==0)
break;
AddEdge(u, v);
AddEdge(v, u);
}
dfs(1, 0);
cout << max(dp[1][0], dp[1][1]) << endl;
}
return 0;
}
/*
*
* 树形DP
*
*/
#include <iostream>
#include <cstring>
using namespace std;
#define N 6010
#define M 12010
int head[N], eNum;
struct Edge
{
int e, next;
}edge[M];
int dp[N][2], num[N];
int max(int x, int y)
{
return x > y ? x : y;
}
void AddEdge(int u, int v)
{
edge[eNum].e = v;
edge[eNum].next = head[u];
head[u] = eNum++;
}
void dfs(int u, int fa)
{
//if(vis[u]) return ;
//vis[u] = 1;
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].e;
if(v == fa) continue;
dfs(v, u);
dp[u][1] += dp[v][0];
dp[u][0] += max(dp[v][0], dp[v][1]);
}
dp[u][1] += num[u];
}
int main()
{
int n;
while(cin >> n)
{
for(int i=1; i<=n; i++)
cin >> num[i];
memset(dp,0,sizeof(dp));
memset(head,-1,sizeof(head));
//memset(vis,0,sizeof(vis));
eNum = 0;
int u, v;
while(cin >> u >> v)
{
if(u==0 && v==0)
break;
AddEdge(u, v);
AddEdge(v, u);
}
dfs(1, 0);
cout << max(dp[1][0], dp[1][1]) << endl;
}
return 0;
}
*
* 树形DP
*
*/
#include <iostream>
#include <cstring>
using namespace std;
#define N 6010
#define M 12010
int head[N], eNum;
struct Edge
{
int e, next;
}edge[M];
int dp[N][2], num[N];
int max(int x, int y)
{
return x > y ? x : y;
}
void AddEdge(int u, int v)
{
edge[eNum].e = v;
edge[eNum].next = head[u];
head[u] = eNum++;
}
void dfs(int u, int fa)
{
//if(vis[u]) return ;
//vis[u] = 1;
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].e;
if(v == fa) continue;
dfs(v, u);
dp[u][1] += dp[v][0];
dp[u][0] += max(dp[v][0], dp[v][1]);
}
dp[u][1] += num[u];
}
int main()
{
int n;
while(cin >> n)
{
for(int i=1; i<=n; i++)
cin >> num[i];
memset(dp,0,sizeof(dp));
memset(head,-1,sizeof(head));
//memset(vis,0,sizeof(vis));
eNum = 0;
int u, v;
while(cin >> u >> v)
{
if(u==0 && v==0)
break;
AddEdge(u, v);
AddEdge(v, u);
}
dfs(1, 0);
cout << max(dp[1][0], dp[1][1]) << endl;
}
return 0;
}
/*
*
* 树形DP
*
*/
#include <iostream>
#include <cstring>
using namespace std;
#define N 6010
#define M 12010
int head[N], eNum;
struct Edge
{
int e, next;
}edge[M];
int dp[N][2], num[N];
int max(int x, int y)
{
return x > y ? x : y;
}
void AddEdge(int u, int v)
{
edge[eNum].e = v;
edge[eNum].next = head[u];
head[u] = eNum++;
}
void dfs(int u, int fa)
{
//if(vis[u]) return ;
//vis[u] = 1;
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].e;
if(v == fa) continue;
dfs(v, u);
dp[u][1] += dp[v][0];
dp[u][0] += max(dp[v][0], dp[v][1]);
}
dp[u][1] += num[u];
}
int main()
{
int n;
while(cin >> n)
{
for(int i=1; i<=n; i++)
cin >> num[i];
memset(dp,0,sizeof(dp));
memset(head,-1,sizeof(head));
//memset(vis,0,sizeof(vis));
eNum = 0;
int u, v;
while(cin >> u >> v)
{
if(u==0 && v==0)
break;
AddEdge(u, v);
AddEdge(v, u);
}
dfs(1, 0);
cout << max(dp[1][0], dp[1][1]) << endl;
}
return 0;
}