树上dp入门

树形dp就是把操作放在树上。

1. P1352 没有上司的舞会 ——树的最大独立集

题意:上司如果参加酒会,下属就不去了。很容易想到上司和员工之间的关系就是父节点与子节点的关系,用boss[i]来存储i的父节点编号。因为编号是1-n的嘛,我们就初始化boss[]为0,然后遍历知道根节点,显然,没有父节点的那个为根节点(boss[i]==0).

状态定义dp[i][0]为i不参加时i和他的下属制造的最大欢乐度

dp[i][0]为i参加时i和他的下属制造的最大欢乐度

#include
#include
#include
#include
using namespace std;
const int maxn=6e3+10;
int a[maxn];
int n,boss[maxn],dp[maxn][2];
vector E[maxn];

void dfs(int x){
	dp[x][0]=0;
	dp[x][1]=a[x];
	for(int i=0;i

 

2.工人的请愿书(Another Crisis UVA - 12186 ) 算法竞赛入门经典 P282

 

因为要排序,算法的时间复杂度为O(nlogn) 。

#include
#include
#include
#include
using namespace std;

const int maxn = 100000 + 5;

int n, t;
vector sons[maxn];


int dp(int u)  //dp(u)表示让u给上级发信最少需要多少个工人。工人也就是叶子节点
{
    if (sons[u].empty())  return 1;
    vector d;
    int k = sons[u].size();
    for (int i = 0; i < k; i++)
        d.push_back(dp(sons[u][i]));
    sort(d.begin(), d.end());
    //int c = (k*t - 1) / 100 + 1; //上取整语句,等价于下边那一句
    int c=ceil(k*t/100.0);
    //cout<<"c="<#include
#include
#include
#include
using namespace std;
const int maxn=1e5+10;
vector sons[maxn];
int n,t;

int dp(int x){
    if(sons[x].empty()) return 1;
    int ans=0;
    int k=sons[x].size();
    vector w;
    for(int i=0;i

你可能感兴趣的:(树上dp)