lanqiao3517 砍树(LCA+树上差分)
This commit is contained in:
90
14lanqiao/test10-2.cpp
Normal file
90
14lanqiao/test10-2.cpp
Normal 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
|
||||||
|
*/
|
||||||
Reference in New Issue
Block a user