第十四届蓝桥杯省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';
}
相关推荐
qq_459234426 天前
【题库】| 商用密码应用安全性评估从业人员考核题库(四十)
职场和发展·密码学·学习方法·考核·商用密码·商用密码应用安全性评估·密评
敲敲了个代码6 天前
[特殊字符] 空数组的迷惑行为:为什么 every 为真,some 为假?
前端·javascript·react.js·面试·职场和发展
诚思报告YH6 天前
视频面试软件市场洞察:2026 - 2032年复合年均增长率(CAGR)为10.3%
面试·职场和发展
重生之后端学习6 天前
74. 搜索二维矩阵
开发语言·数据结构·算法·职场和发展·深度优先
tyb3333336 天前
leetcode:吃苹果和队列
算法·leetcode·职场和发展
Pitiless-invader6 天前
MySQL 相关知识及面试问题汇总
面试·职场和发展
重生之后端学习6 天前
35. 搜索插入位置
java·数据结构·算法·leetcode·职场和发展·深度优先
逆境不可逃6 天前
【从零入门23种设计模式08】结构型之组合模式(含电商业务场景)
线性代数·算法·设计模式·职场和发展·矩阵·组合模式
筱昕~呀6 天前
冲刺蓝桥杯-DFS板块(第二天)
算法·蓝桥杯·深度优先
zheshiyangyang6 天前
前端面试基础知识整理【Day-10】
前端·面试·职场和发展