Bootstrap

19032 树上上升序列

### 思路
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;
}

;