当前位置: 首页 > news >正文

[蓝桥杯 2023 省 A] 网络稳定性

题目来自DOTCPP:

 思路:

①由于题目没有告诉我们成树形结构,可能成环。因此,我们要自己构建树。

②本体我们通过kruskal重构树,按边权从大到小排序,那么查询的两个点的最近公共祖先权值就是答案。

③在通过树链剖分找到树上两个节点的最近公共祖先 ,就能找到答案了。

代码实现:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 3e5+20;

int n, m, q;
//kruskal重构树
struct edge{//记录边的信息
    int u, v, w;
}e[N];
vector<int> t[N];//记录重构的树
int fa[N];//判断两个点是否联通,可以建树
int val[N]; //用来记录这个点的点权

//找到x根节点
int find(int x){
    if(fa[x] == x) return x;
    return fa[x] = find(fa[x]);
}

//重构树
void kruskal(){
    //对fa初始化,每个节点父节点为本身
    for(int i = 1; i <= 2*n; i++)fa[i] = i;
    //对e根据e.w排序,根据题目决定大到小/小到大
    sort(e, e+m, [&](edge x, edge y){return x.w > y.w;});
    //新节点 
    int idx = n;
    
    for(int i = 0; i < m; i++){
        //取出节点
        int x = e[i].u, y = e[i].v;
        //找到节点顶点
        int xx = find(x), yy = find(y);
        //如果两个节点在一个集合中,跳过
        if(xx == yy) continue;
        idx++;//新节点+1
        //指向父节点
        fa[xx] = fa[yy] = idx;
        //记录这课树
        t[idx].push_back(xx);
        t[idx].push_back(yy);
        //更新这个点的权值
        val[idx] = e[i].w;
    }
}

//树链剖分
int fa1[N], sz[N], dep[N], son[N], top[N];

void dfs1(int u, int father){
    fa1[u] = father, dep[u] = dep[father] +1, sz[u] = 1;
    for(auto v: t[u]){
        if(v == fa1[u]) continue;
        dfs1(v, u);
        sz[u] += sz[v];
        if(sz[son[u]] < sz[v]) son[u] = v;
    }
}

void dfs2(int u, int tt){
    top[u] = tt;
    if(!son[u])return;
    dfs2(son[u], tt);
    
    for(auto v: t[u]){
        if(v == fa1[u] || v == son[u]) continue;
        dfs2(v, v);
    }
}

int lca(int u, int v){
    while(top[u] != top[v]){
        if(dep[top[u]] < dep[top[v]]) swap(u, v);
        u = fa1[top[u]];
    }
    return dep[u] < dep[v] ? u:v;
}

signed main(){
    scanf("%lld %lld %lld", &n, &m, &q);
    for(int i = 0; i < m; i++){
        scanf("%lld %lld %lld", &e[i].u, &e[i].v, &e[i].w);
    }
    //开始重构树
    kruskal();
    //对树预处理,要找到树的顶点
    for(int i = 1; i <= 2*n; i++){
        if(fa[i] == i){
            //树链剖分预处理模板
            dfs1(i, 0);
            dfs2(i, i);
        }
    }
    
    //输出询问的答案
    while(q--){
        //找到 x,y的根节点,判断是否在一个集合下
        int x, y; scanf("%lld %lld", &x, &y);
        int xx = find(x), yy = find(y);
        if(xx != yy) printf("-1\n");
        else{
            //找到x,y最近公共祖先
            int ans = lca(x, y);
            //ans的点权就是答案
            printf("%lld\n", val[ans]);
        }
    }
    return 0;
}

相关文章:

  • 鸿蒙富文本实践
  • RK3588使用笔记:系统换源
  • 【YOLO系列】基于YOLOv8的无人机野生动物检测
  • 【NLP】14. NLP推理方法详解 --- beam search 束搜索 以及 graph search 图搜索
  • Nginx学习笔记(一)
  • 人工智能图像识别Scala基础
  • Vue2——组件的注册与通信方式、默认插槽、具名插槽、插槽的作用域
  • 数智化时代下开源AI大模型驱动的新型商业生态构建——基于AI智能名片与S2B2C商城小程序的融合创新研究
  • PH热榜 | 2025-03-30
  • 机器学习:人工智能的核心驱动力
  • windows权限提升 win+iss 宝塔bypass Msf进行提取
  • 优秀的 Vue.js 入门开源项目推荐
  • Python第七章01:文件的读取操作
  • AI 强化学习
  • Shell教程
  • 【质量管理】纠正、纠正措施和预防的区别与解决问题的四重境界
  • 移动端六大语言速记:第2部分 - 控制结构
  • SpringBoot实现RBAC权限校验模型
  • 拓展知识六:MetInfo6.0.0目录遍历漏洞原理分析
  • 二分算法到红蓝染色
  • 上海高端品牌网站建设/百度seo搜索排名
  • 网站升级方案/网站seo软件
  • 网站开发 电话/seo优化收费
  • 知名网站建设/济南网站优化公司哪家好
  • 微信小程序分销系统/南京seo公司教程
  • 网站建网站建设/seo博客教程