题目描述
给定一棵由 n 个结点组成的树以及 m 个不重复的无序数对 (a1,b1),(a2,b2),…,(am,bm),其中 ai 互不相同,bi 互不相同,ai=bj(1≤i,j≤m)。
小明想知道是否能够选择一条树上的边砍断,使得对于每个 (ai,bi) 满足 ai 和 bi 不连通,如果可以则输出应该断掉的边的编号 (编号按输入顺序从 1 开始),否则输出 -1
。
输入格式
输入共 n+m 行,第一行为两个正整数 n,m。
后面 n−1 行,每行两个正整数 xi,yi 表示第 i 条边的两个端点。
后面 m 行,每行两个正整数 ai,bi。
输出格式
一行一个整数,表示答案,如有多个答案,输出编号最大的一个。
输入输出样例
输入 #1
6 2 1 2 2 3 4 3 2 5 6 5 3 6 4 5
输出 #1
4
前置知识:1.树上差分 ,2.LCA (最近公共祖先)
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#include<deque>
#include<stack>
#include<set>
#include<map>
#include<unordered_set>
#include<unordered_map>
#include<bitset>
#include<tuple>
#define inf 9187201950435737471
#define int long long
#define endl '\n'
#define F first
#define S second
#define mst(a,x) memset(a,x,sizeof (a))
using namespace std;
typedef pair<int, int> pii;
const int N = 200086, mod = 998244353;
int n, m;
int h[N], ne[N], e[N], w[N], idx;
int dp[N], fa[N][21];
int pw[N];
int res = -1;
void add(int a, int b, int c) {
w[idx] = c; //给边权计为标号i
e[idx] = b;
ne[idx] = h[a];
h[a] = idx++;
}
void bfs() {
mst(dp, 127);
queue<int> q;
dp[0] = 0, dp[1] = 1;
q.push(1);
while (q.size()) {
int u = q.front();
q.pop();
for (int i = h[u]; ~i; i = ne[i]) {
int j = e[i];
if (dp[j] > dp[u] + 1) {
dp[j] = dp[u] + 1;
q.push(j);
fa[j][0] = u;
for (int k = 1; k <= 20; k++) {
fa[j][k] = fa[fa[j][k - 1]][k - 1];//倍增打表
}
}
}
}
}
int lca(int a, int b) {
if (dp[a] < dp[b]) swap(a, b);
for (int i = 20; i >= 0; i--) {
if (dp[fa[a][i]] >= dp[b]) a = fa[a][i];
}
if (a == b) return a;
for (int i = 20; i >= 0; i--) {
if (fa[a][i] != fa[b][i]) {
a = fa[a][i];
b = fa[b][i];
}
}
return fa[a][0];
}
void dfs(int u, int fa) {
for (int i = h[u]; ~i; i = ne[i]) {
int j = e[i];
if (j == fa) continue;
dfs(j, u);
pw[u] += pw[j];//累加
if (pw[j] == m) res = max(res, w[i]);//求最大边的编号
}
}
void solve() {
mst(h, -1);
cin >> n >> m;
for (int i = 1; i < n; i++) {
int a, b;
cin >> a >> b;
add(a, b, i), add(b, a, i);
}
bfs();
for (int i = 1; i <= m; i++) {
int a, b;
cin >> a >> b;
pw[a]++, pw[b]++;
pw[lca(a, b)] -= 2;//边差分
}
dfs(1, -1);
cout << res << endl;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int T = 1;
// cin >> T;
while (T--) solve();
return 0;
}