目录
涵义
涵义由两个问题引出:
什么是树?
1.层次性
2.递归性
3.N-1连通性(判断一个图是树的方法)
什么是dp?
1.阶段性
2.最优子结构性
3.无后效性
转移
层次—>阶段
子树—>最优子结构·
1.自底向上:类似于拓扑排序
2.自上向下:递归实现(后序遍历)
例题
P1352 没有上司的舞会 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
这道题不难看出是树结构,用邻接表处理即可
如下:
对于每个节点 i 状态描述:用1和0表示来与不来——f[i][1]和f[i][0]
转移方程如下:
这题选择自下而上dfs
样码
写法1——
#include<bits/stdc++.h>
using namespace std;
const int N=10000;
int n,happy[N],dp[N][2],head[N],cnt;
struct node
{
int v;
int nxt;
}tree[N*2];
void addedge(int u,int v)
{
tree[++cnt]=node{v,head[u]};
head[u]=cnt;
}
void dfs(int x,int fa)
{
for(int i=head[x];i;i=tree[i].nxt)
{
int y=tree[i].v;
if(y==fa) continue;//这一步一定要判,不然会死循环
dfs(y,x);
dp[x][1]+=dp[y][0];
dp[x][0]+=max(dp[y][1],dp[y][0]);
}
dp[x][1]+=happy[x];
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)scanf("%d",&happy[i]);
int l,k;
for(int i=1;i<n;++i)
{
scanf("%d%d",&l,&k);
addedge(l,k);
addedge(k,l);
}
dfs(1,0);
cout<<max(dp[1][1],dp[1][0]);
return 0;
}
写法2——
#include<bits/stdc++.h>
using namespace std;
const int N=10000;
int n,happy[N],root,y[N],dp[N][2];
vector<int> son[N];
void dfs(int root)
{
for(int i=0;i<root[son].size();i++)
{
int y=root[son][i];
dfs(y);
dp[root][1]+=dp[y][0];
dp[root][0]+=max(dp[y][1],dp[y][0]);
}
dp[root][1]+=happy[root];
}
int main()
{
cin>>n;
for(int i=1;i<=n;++i)cin>>happy[i];
int l,k;
for(int i=1;i<n;++i)
{
cin>>l>>k;
y[l]=1;
son[k].push_back(l);
}
for(int i=1;i<=n;++i)
if(!y[i]) root=i;
dfs(root);
cout<<max(dp[root][1],dp[root][0]);
return 0;
}