### 思路
1. **输入处理**:读取节点个数、点权和边。
2. **构建图**:将树转换为有向无环图(DAG),边的方向从点权小的指向点权大的。
3. **拓扑排序**:对DAG进行拓扑排序。
4. **动态规划**:使用动态规划求解最长路径。
### 细节
- **图的构建**:遍历所有边,根据点权大小确定边的方向。
- **拓扑排序**:使用Kahn算法或DFS进行拓扑排序。
- **动态规划**:初始化每个节点的最长路径长度为1,按照拓扑排序的顺序更新每个节点的最长路径长度。
### 伪代码
```plaintext
function longest_increasing_path(n, a, edges):
graph = build_graph(n, a, edges)
topo_order = topological_sort(graph)
dp = array of size n initialized to 1
for node in topo_order:
for neighbor in graph[node]:
if a[node] < a[neighbor]:
dp[neighbor] = max(dp[neighbor], dp[node] + 1)
return max(dp)
function build_graph(n, a, edges):
graph = adjacency list of size n
for u, v in edges:
if a[u-1] < a[v-1]:
graph[u-1].append(v-1)
else:
graph[v-1].append(u-1)
return graph
function topological_sort(graph):
in_degree = array of size n initialized to 0
for node in graph:
for neighbor in graph[node]:
in_degree[neighbor] += 1
queue = empty queue
for i in range(n):
if in_degree[i] == 0:
queue.push(i)
topo_order = empty list
while queue is not empty:
node = queue.pop()
topo_order.append(node)
for neighbor in graph[node]:
in_degree[neighbor] -= 1
if in_degree[neighbor] == 0:
queue.push(neighbor)
return topo_order
```
### C++代码
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
vector<vector<int>> build_graph(int n, const vector<int>& a, const vector<pair<int, int>>& edges) {
vector<vector<int>> graph(n);
for (const auto& edge : edges) {
int u = edge.first - 1;
int v = edge.second - 1;
if (a[u] < a[v]) {
graph[u].push_back(v);
} else {
graph[v].push_back(u);
}
}
return graph;
}
vector<int> topological_sort(const vector<vector<int>>& graph) {
int n = graph.size();
vector<int> in_degree(n, 0);
for (const auto& neighbors : graph) {
for (int neighbor : neighbors) {
in_degree[neighbor]++;
}
}
queue<int> q;
for (int i = 0; i < n; ++i) {
if (in_degree[i] == 0) {
q.push(i);
}
}
vector<int> topo_order;
while (!q.empty()) {
int node = q.front();
q.pop();
topo_order.push_back(node);
for (int neighbor : graph[node]) {
in_degree[neighbor]--;
if (in_degree[neighbor] == 0) {
q.push(neighbor);
}
}
}
return topo_order;
}
int longest_increasing_path(int n, const vector<int>& a, const vector<pair<int, int>>& edges) {
vector<vector<int>> graph = build_graph(n, a, edges);
vector<int> topo_order = topological_sort(graph);
vector<int> dp(n, 1);
for (int node : topo_order) {
for (int neighbor : graph[node]) {
if (a[node] < a[neighbor]) {
dp[neighbor] = max(dp[neighbor], dp[node] + 1);
}
}
}
return *max_element(dp.begin(), dp.end());
}
int main() {
int n;
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; ++i) {
cin >> a[i];
}
vector<pair<int, int>> edges(n - 1);
for (int i = 0; i < n - 1; ++i) {
cin >> edges[i].first >> edges[i].second;
}
cout << longest_increasing_path(n, a, edges) << endl;
return 0;
}