倍增LCA(带修改),codeforce#535F,codeforce#827D

本文介绍了如何运用倍增LCA算法解决两个Codeforces竞赛中的问题:F. MST Unification 和 D. Best Edge Weight。这两个问题都涉及最小生成树(MST)的构建和操作,通过寻找树边上的最小值和非树边的最大值来确定操作次数或权重限制。题解部分详细阐述了如何利用倍增LCA高效地查找路径上的最小值,并提供了问题的解决方案和代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

F. MST Unification

https://codeforces.com/contest/1108/problem/F

题意

n个点,m条边,每条边都有一个权值,每次操作可以使得一条边的权值减1,问最小需要几次操作,使得最小生成树唯一。

题解

对于最小生成树不唯一的情况就是,添加一条非树边后(u,v,w)后构成的环中的最小值(除非树边的最小值)等于非树边,这样就可以用非树边去替代这条边使得最小生成树不唯一,所以先构造一棵最小生成树,然后只需要对每条非树边(u,v,w)查询树边u到v中的最小值是否等于w,若等于则需要的操作+1。
这里查找树上(u,v)之间的最小值采用的是倍增LCA的方法。

代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <vector>
using namespace std;

const int maxn = 2e5+5;

int _max[maxn][20];
int dep[maxn];
struct Edge{
   
    int v,c;
    Edge(int _v,int _c):v(_v),c(_c){
   }
};
vector<Edge> G[maxn];
int n,m;

void add(int f,int v,int c) {
   
    G[f].push_back(Edge(v,c));
}
int p[maxn][20];
void dfs(int u,int fa) {
   
    for(int i = 0; i < G[u].size(); ++i) {
   
        int v = G[u][i].v;
        if(v == fa) continue;
        _max[v][0] = G[u][i].c;
        dep[v] = dep[u]+1;
        p[v][0] = u;
        dfs(v,u);
    }
}
void initLCA() {
   
    for(int i = 1; i <= 18; ++i)
        for(int j = 1; j <= n; ++j)  {
   
            p[j][i] = p[p[j][i-1]][i-1];
            _max[j][i] = max(_max[j][i-1],_max[p[j][i-1]][i-1]);
        }
}
int LCA(int x,int y) {
   
    if(dep[x] < dep[y])
        swap(x,y);
    int ans = 0;
    for(int i = 18; i >= 0; --i)
        if(dep[p[x][i]] >= dep[y]) {
   
            ans = max(ans, _max[x][i]);
            x = p[x][i];

        }
    if(x == y)
        return ans;
    for(int i = 18; i >= 0; --i) {
   
        if(p[x][i] != p[
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值