lanqiao3517 砍树(LCA+树上差分)

This commit is contained in:
2025-03-18 19:46:15 +08:00
parent 75d40389df
commit d7c4556e6b

90
14lanqiao/test10-2.cpp Normal file
View File

@@ -0,0 +1,90 @@
// lanqiao3517 砍树(LCA+树上差分)
#include<bits/stdc++.h>
using namespace std;
const int N = 5e5 + 10;
// 链式前向量存储图
int edges[N], next_edge[N], head[N], edge_idx;
int fa[N][25], depth[N], subtree_pairs[N];
int n, m;
// 添加一条边
void addEdge(int s, int t){
edges[edge_idx] = t;
next_edge[edge_idx] = head[s];
head[s] = edge_idx++;
}
// 深度搜索优先并记录每个节点的深度与祖先信息
void dfs(int cur, int parent, int dep){
fa[cur][0] = parent;
depth[cur] = dep;
for(int i = 1; i <= 20; i++){
fa[cur][i] = fa[fa[cur][i-1]][i-1]; // 动态规划处理快速求最近
}
for(int i = head[cur]; i != -1; i = next_edge[i]){
int child = edges[i];
if(child == parent) continue;
dfs(child, cur, dep + 1);
}
}
int LCA(int x, int y){
if(depth[x] < depth[y]) swap(x, y);
// 将x向上跳到与y同一深度或更浅的位置
for(int i = 20; i >= 0; i--){
if(depth[fa[x][i]] >= depth[y]){
x = fa[x][i];
}
}
if(x == y) return x;
for(int i = 20; i >= 0; i--){
if(fa[x][i] != fa[y][i]){
x = fa[x][i];
y = fa[y][i];
}
}
return fa[x][0]; // 返回最近公共祖先
}
void updateSubtreePairs(int cur, int parent, int edgeId, int& maxEdgeId){
for(int i = head[cur]; i != -1; i = next_edge[i]){
int child = edges[i];
if(child == parent) continue;
updateSubtreePairs(child, cur, i, maxEdgeId); // 递归更新子节点
subtree_pairs[cur] += subtree_pairs[child];
}
// 当前节点及其子树内包含m对点对时更新答案
if(subtree_pairs[cur] == m){
maxEdgeId = max(maxEdgeId, edgeId / 2 + 1); // 边的编号减半(因为是无向图, 一条边有两个方向的编号)
}
}
int main(){
cin >> n >> m;
// 初始化邻接表
for(int i = 1; i <= n; i++) head[i] = -1;
// 读入树的边并建立邻接表
for(int i = 1; i < n; i++){
int u, v;
cin >> u >> v;
addEdge(u, v); addEdge(v, u);
}
// 深度优先搜索预处理节点深度与祖先信息
dfs(1, 0, 1);
for(int i = 1; i <= m; i++){
int firstNode, secondNode;
cin >> firstNode >> secondNode;
subtree_pairs[firstNode]++;
subtree_pairs[secondNode]++;
subtree_pairs[LCA(firstNode, secondNode)] -= 2;
}
int ans = -1;
updateSubtreePairs(1, 0, 0, ans);
cout << ans;
return 0;
}
/* test samples -> 4
6 2
1 2
2 3
4 3
2 5
6 5
3 6
4 5
*/