十四届省赛真题-砍树

115 阅读2分钟

题目描述

给定一棵由 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;
}