题意:给你一个连通图,有n-1条边,以及每个点都有一个权值,让你求出权值单调上升的路径的最长长度
思路:树形dp题,用一个数组dpup[i]表示以i为根的的最长上升路径的长度,dpdown[i]表示以i为根的最长下降路径的长度,那么以i为根的路径长度最长就是dpup[i]+dpdown[i]+1,遍历每一个根的节点,用dfs搜索得出最大值
#include <bits/stdc++.h>
using namespace std;
//树形dp,完全没想到
const int N = 1e6 + 10;
int a[N];
int b, c;
int n;
int maxn = 0;
vector<int> v[N];
int dpup[N]; //以节点N为跟的最长上升子序列的长度
int dpdown[N]; //以节点N为跟的最长下降子序列的长度
void dfs(int now, int fuck)
{
// dpup[1] = 1;
// dpdown[1] = 1;
for (auto t : v[now])
{
if (t == fuck)
{
continue;
}
dfs(t, now);
if (a[t] < a[now])
{
dpdown[now] = max(dpdown[t] + 1, dpdown[now]);
}
else if (a[t] > a[now])
{
dpup[now] = max(dpup[t] + 1, dpup[now]);
}
}
maxn = max(maxn, dpup[now] + dpdown[now] + 1); //加一是因为这里求的是在now上面的和now下面的,但没有包括now本身,这个1就相当于是now
// printf("%d\n", now);
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n - 1; i++)
{
scanf("%d%d", &b, &c);
v[b].push_back(c);
v[c].push_back(b);
}
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
}
dfs(1, 1);
printf("%d\n", maxn);
return 0;
}