树形dp
简单来说树形
d
p
就是在树上做
d
p
罢了
简单来说树形dp就是在树上做dp罢了
简单来说树形dp就是在树上做dp罢了
树嘛,就要符合除了根节点外每个节点只有一个父节点
树嘛,就要符合除了根节点外每个节点只有一个父节点
树嘛,就要符合除了根节点外每个节点只有一个父节点
然后分析
d
p
的时候,不再是线性的前几的什么属性那种线性术语了
然后分析dp的时候,不再是线性的前几的什么属性那种线性术语了
然后分析dp的时候,不再是线性的前几的什么属性那种线性术语了
而是以
i
为根节点的树的各种属性
而是以i为根节点的树的各种属性
而是以i为根节点的树的各种属性
状态转移也从原本的前
i
−
1
到前
i
个转移
状态转移也从原本的前i-1到前i个转移
状态转移也从原本的前i−1到前i个转移
而是
u
的子树向
u
为根的树转移
而是 u的子树向u为根的树转移
而是u的子树向u为根的树转移
上几道例题具体分析
例题一
思路
AC代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1e4 + 10;
int h[N], e[N], w[N], ne[N], idx;
bool st[N];
int n;
int f[N][3]; //1:最长 0 次长
int res = -0x3f3f3f3f;
void add(int a, int b, int c){
e[idx] = b;
ne[idx] = h[a];
w[idx] = c;
h[a] = idx ++;
}
void dfs(int u)
{
for(int i = h[u]; i != -1; i = ne[i])
{
int j = e[i];
dfs(j);
if(f[j][1] + w[i] >= f[u][1]){
f[u][0] = f[u][1];
f[u][1] = f[j][1] + w[i];
}
else if(f[j][1] + w[i] > f[u][0])
{
f[u][0] = f[j][1] + w[i];
}
}
}
int main()
{
cin >> n;
memset(h, -1, sizeof(h));
for(int i = 1; i <= n - 1; i ++)
{
int a, b, c;
cin >> a >> b >> c;
add(a, b, c);
st[b] = true;
}
int root = 1;
while(st[root]) root ++;
dfs(root);
for(int i = 1; i <= n; i ++)
{
res = max(res, f[i][0] + f[i][1]);
}
cout << res << endl;
return 0;
}
例题2
#include<bits/stdc++.h>
using namespace std;
const int N = 1e4 + 10;
int h[N], e[N<<1], w[N<<1], ne[N<<1], idx;
int n;
int down1[N], down2[N], up[N], best[N], second[N];
void add(int a, int b, int c)
{
e[idx] = b;
w[idx] = c;
ne[idx] = h[a];
h[a] = idx ++;
}
void dfs_d(int u, int fa)
{
for(int i = h[u]; i != -1; i = ne[i])
{
int j = e[i];
if(j == fa) continue;
dfs_d(j, u);
if(down1[j] + w[i] >= down1[u])
{
down2[u] = down1[u];
second[u] = best[u];
best[u] = j;
down1[u] = down1[j] + w[i];
}
else if(down1[j] + w[i] > down2[u])
{
down2[u] = down1[j] + w[i];
second[u] = j;
}
}
}
void dfs_u(int u, int fa)
{
for(int i = h[u]; i != -1; i = ne[i])
{
int j = e[i];
if(j == fa) continue;
if(j == best[u])
{
up[j] = max(up[u], down2[u]) + w[i];
}
else
{
up[j] = max(up[u], down1[u]) + w[i];
}
dfs_u(j, u);
}
}
int main()
{
memset(h, -1, sizeof(h));
cin >> n;
for(int i = 1; i <= n - 1; i ++)
{
int a, b, c;
cin >> a >> b >> c;
add(a, b, c), add(b, a, c);
}
dfs_d(1, -1);
dfs_u(1, -1);
int res = 1e9;
for(int i = 1; i <= n; i ++)
{
res = min(max(down1[i], up[i]), res);
}
cout << res << endl;
return 0;
}