题目描述
给定一棵由 n 个结点组成的树以及 m 个不重复的无序数对 (a1, b1), (a2, b2), . . . , (am, bm),其中 ai 互不相同,bi 互不相同,ai ≠ bj(1 ≤ i, j ≤ m)。 小明想知道是否能够选择一条树上的边砍断,使得对于每个 (ai , bi) 满足 ai和 bi 不连通,如果可以则输出应该断掉的边的编号(编号按输入顺序从 1 开始),否则输出 -1.
输入格式
一行一个整数,表示答案,如有多个答案,输出编号最大的一个。
输出
行一个整数,表示答案,如有多个答案,输出编号最大的一个。
思路
我们考虑给u->v经过得边边权加一代表这条边我们经过一次同理可得如果边权是m代表我们经过m次也就是如果断掉这条边经过这条边的两个点将无法联通
Code
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define int long long
#define endl '\n'
#define pb push_back
#define NO cout << "NO" << endl;
#define YES cout << "YES" << endl;
#define fi first
#define se second
#define all(x) (x).begin(),(x).end()
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,a,n) for (int i=n;i>=a;i--)
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<VI> VII;
ll MOD = 998244353;
ll powmod(ll a,ll b) {ll res=1;a%=MOD; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%MOD;a=a*a%MOD;}return res;}
const int N = 2e5 + 10;
void solve()
{
int n, m; cin >> n >> m;
vector<vector<PII>> e(n + 1);
vector<PII> a(n + 1);
rep (i, 1, n - 1) {
int u, v; cin >> u >> v;
a[i] = {u, v};
e[u].pb({v, i});
e[v].pb({u, i});
}
VI de(n + 1), p(n + 1), s(n + 1);
VII f(n + 1, VI(23));
function<void(int, int)> dfs = [&] (int u, int fa) {
de[u] = de[fa] + 1;
f[u][0] = fa;
for (auto [v, w] : e[u]) if (v != fa) dfs(v, u);
};
dfs(1, 0);
for (int j = 1; j < 20; j++)
for (int i = 1; i <= n; i++) f[i][j] = f[f[i][j-1]][j-1];
function<int(int, int)> Lca = [&] (int x, int y) {
if (de[x] < de[y]) swap(x, y);
for (int i = 19; i >= 0; i--) {
if (de[f[x][i]] >= de[y]) {
x = f[x][i];
}
}
if (x == y) return x;
for (int i = 19; i >= 0; i--) {
if (f[x][i] != f[y][i]) {
x = f[x][i];
y = f[y][i];
}
}
return f[x][0];
};
function<void(int, int)> dfs1 = [&] (int u, int fa) {
for (auto [v, w] : e[u]) {
if (v == fa) continue;
dfs1(v, u);
s[u] += s[v];
}
};
rep (i, 1, m) {
int u, v; cin >> u >> v;
int fa = Lca(u, v);
s[u] ++, s[v] ++;
s[fa] -= 1;
s[f[fa][0]] -= 1;
}
dfs1(1, 0);
// rep (i, 1, n) cout << s[i] << " \n"[i == n];
per (i, 1, n - 1) {
auto [u, v] = a[i];
if (s[u] == m && s[v] == m) {
cout << i << endl;
return;
}
}
cout << -1 << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
// int T;cin >> T;
// while ( T -- )
solve();
return 0;
}