第十四届蓝桥杯省B.砍树

第十四届蓝桥杯省B.砍树

题目

题目解析及思路

考虑一对无序数对的点 x和 y,如果我们砍掉某条边可以让这两个点不连通 ,那么这条边一定是从 x到 y 路径上的一点 ,我们可以让从 x到 y 路径的边权值都加1 。这个操作我们可以使用树上差分 。 对于 m个无序数对我们都如此操作,最后如果某条边的权值为 m 则说明它符合条件,我们选出符合条件编号最大的那条边就是答案,如果没有权值为 m的边则说明无解。

树上差分

代码

cpp 复制代码
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define pii pair<int,int>
#define ms(s,x) memset(s, x, sizeof(s))
using namespace std;
typedef pair<int,int> PII;
const int inf = 0x3f3f3f3f;
const int mod = 1000000007;
const int N = 200010;

int n, m;
vector<int> e[N];
int depth[N], fa[N][16];
int f[N];
int root;
int ans;
map<PII, int> mp;

//lca板子
void bfs(int root){
    memset(depth,0x3f,sizeof(depth));
    depth[0] = 0,depth[root] = 1;
    queue<int> q;
    q.push(root);
    
    while(!q.empty()){
        int t = q.front();
        q.pop();
        for(int j:e[t]){
            if(depth[j] > depth[t] + 1){
                depth[j] = depth[t] + 1;
                q.push(j);
                fa[j][0] = t;
                for(int k=1;k<=15;k++){
                    fa[j][k] = fa[fa[j][k-1]][k-1];
                }
            }
        }
    }
}

int lca(int a,int b){
    if(depth[a] < depth[b]) swap(a,b);
    for(int k=15;k>=0;k--){
        if(depth[fa[a][k]] >= depth[b]){
            a = fa[a][k];
        }
    }
    if(a == b) return a;
    for(int k=15;k>=0;k--){
        if(fa[a][k] != fa[b][k]){
            a = fa[a][k];
            b = fa[b][k];
        }
    }
    return fa[a][0];
}
//对树上差分数组f进行dfs求和
int dfs(int u,int fa){
    int res = f[u];
    for(auto v:e[u]){
        if(v == fa) continue;
        int g = dfs(v,u);
        if(g == m){
            ans = max(ans,mp[{v,u}]);
        }
        res += g;
    }
    return res;
}
signed main(){
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(false);
    
    ans = 0;
    cin>>n>>m;
    for(int i=0;i<n-1;i++){
        int u,v;
        cin>>u>>v;
        mp[{u,v}] = mp[{v,u}] = i+1;
        e[u].push_back(v);
        e[v].push_back(u);
    }
    //lca
    bfs(1);
    //树上差分
    for(int i=0;i<m;i++){
        int u,v;
        cin>>u>>v;
        int z = lca(u,v);
        f[u] ++;
        f[v] ++;
        f[z] -= 2;
    }
    dfs(1,-1);
    cout << (ans == 0 ? -1 : ans) << '\n';
}
相关推荐
XH华10 小时前
备战蓝桥杯,第九章:结构体和类
学习·蓝桥杯
园小异11 小时前
2026年技术面试完全指南:从算法到系统设计的实战突破
算法·面试·职场和发展
Epiphany.55614 小时前
蓝桥杯备赛题目-----爆破
算法·职场和发展·蓝桥杯
YuTaoShao14 小时前
【LeetCode 每日一题】1653. 使字符串平衡的最少删除次数——(解法三)DP 空间优化
算法·leetcode·职场和发展
Ll130452529819 小时前
Leetcode二叉树part4
算法·leetcode·职场和发展
夏鹏今天学习了吗20 小时前
【LeetCode热题100(99/100)】柱状图中最大的矩形
算法·leetcode·职场和发展
_OP_CHEN21 小时前
【算法基础篇】(五十八)线性代数之高斯消元法从原理到实战:手撕模板 + 洛谷真题全解
线性代数·算法·蓝桥杯·c/c++·线性方程组·acm/icpc·高斯消元法
仰泳的熊猫1 天前
题目1453:蓝桥杯历届试题-翻硬币
数据结构·c++·算法·蓝桥杯
零售ERP菜鸟1 天前
范式革命:从“信息化”到“数字化”的本质跃迁
大数据·人工智能·职场和发展·创业创新·学习方法·业界资讯
网络安全-杰克2 天前
2026面试自动化测试面试题【含答案】
自动化测试·软件测试·面试·职场和发展