P1967 [NOIP2013 提高组] 货车运输 题解

这篇具有很好参考价值的文章主要介绍了P1967 [NOIP2013 提高组] 货车运输 题解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

P1967 [NOIP2013 提高组] 货车运输

原题地址

思路:

由于题目要求的是使两点之间的最小边权最大,所以可以构造最大生成树(最大生成树一定是最大瓶颈生成树,而瓶颈生成树上两点之间的路径,在原图中的所有路径中,最小边权仍然最大,即满足题目要求,详见 https://oi-wiki.org/graph/mst/#瓶颈生成树 ),答案为最大生成树上的路径的最小边权。

求树上路径上的边权最值可以使用 \(LCA\),因为它可以通过合并两个点的 \(LCA\) 和这两个点到 \(LCA\) 的路径的边权最值得来。

做法:

先用 \(Kruskal\) 算出最大生成树,再用倍增的方式计算 \(LCA\),并维护每条路径上的最小边权。

\(e\) 表示初始图,\(G\) 表示最大生成树,\(deep\) 表示点的深度,\(fa_{i,j}\) 表示 \(i\) 的第 \(2^j\) 级祖先,\(w_{i,j}\) 表示 \(i\)\(i\) 的第 \(2^j\) 级祖先的路径上的最小边权,在求 \(LCA\) 的过程中输出经过的点上的最小边权即可。

代码:

时间复杂度:\(\Theta(m\log m + n\log n)\)文章来源地址https://www.toymoban.com/news/detail-844361.html

#include<iostream>
#include<vector>
#include<algorithm>
#define int long long
using namespace std;

const int N = 10010;
const int E = 50010;
const int M = 25;
const int INF = 1e18;

struct Node { int v, w; } ;
struct Edge { int u, v, w; } ;

int n, m, q;
int f[N], fa[N][M], deep[N], w[N][M];
bool vis[N];
Edge e[E];
vector<Node> G[N];

// 排序初始边,用于求最大生成树
bool cmpk(Edge x, Edge y) { return x.w > y.w; } 

int find(int x) // 并查集 - 查找祖先
{
    if(f[x] == x)
        return f[x];
    return f[x] = find(f[x]);
}

void kruskal() // 求最大生成树
{
    sort(e+1, e+m+1, cmpk);
    for(int i=1; i<=n; i++)
        f[i] = i;
    for(int i=1; i<=m; i++)
    {
        int u = e[i].u, v = e[i].v, w = e[i].w;
        if(find(u) == find(v))
            continue;
        f[find(u)] = find(v);
        G[u].push_back({v, w});
        G[v].push_back({u, w});
    }
}

void predfs(int u) // LCA初始化1 - 求出深度、父亲
{
    vis[u] = true;
    for(int i=0; i<G[u].size(); i++)
    {
        int v = G[u][i].v;
        if(vis[v])
            continue;
        deep[v] = deep[u] + 1;
        fa[v][0] = u;
        w[v][0] = G[u][i].w;
        predfs(v);
    }
}

int LCA(int x, int y) // 求LCA和答案
{
    if(find(x) != find(y))
        return -1;
    int ans = INF;
    if(deep[x] > deep[y])
        swap(x, y);
    for(int i=20; i>=0; i--)
    {
        if(deep[fa[y][i]] < deep[x])
            continue;
        ans = min(ans, w[y][i]);
        y = fa[y][i];
    }
    if(x == y)
        return ans;
    for(int i=20; i>=0; i--)
    {
        if(fa[x][i] == fa[y][i])
            continue;
        ans = min(ans, min(w[x][i], w[y][i]));
        x = fa[x][i];
        y = fa[y][i];
    }
    ans = min(ans, min(w[x][0], w[y][0]));
    return ans;
}

void prelca() // LCA初始化2 - 求出祖先
{
    for(int i=1; i<=20; i++)
    {
        for(int j=1; j<=n; j++)
        {
            fa[j][i] = fa[fa[j][i-1]][i-1];
            w[j][i] = min(w[j][i-1], w[fa[j][i-1]][i-1]);
        }
    }
}

signed main()
{
    cin >> n >> m;
    for(int i=1; i<=m; i++)
        cin >> e[i].u >> e[i].v >> e[i].w;
    kruskal();
    for(int i=1; i<=n; i++)
    {
        if(vis[i])
            continue;
        deep[i] = 1;
        predfs(i);
        fa[i][0] = i;
        w[i][0] = INF;
    }
    prelca();
    cin >> q;
    while(q --)
    {
        int x, y; cin >> x >> y;
        cout << LCA(x, y) << '\n';
    }
    return 0;
}

到了这里,关于P1967 [NOIP2013 提高组] 货车运输 题解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【洛谷 P1328】[NOIP2014 提高组] 生活大爆炸版石头剪刀布 题解(模拟+向量)

    石头剪刀布是常见的猜拳游戏:石头胜剪刀,剪刀胜布,布胜石头。如果两个人出拳一样,则不分胜负。在《生活大爆炸》第二季第 8 集中出现了一种石头剪刀布的升级版游戏。 升级版游戏在传统的石头剪刀布游戏的基础上,增加了两个新手势: 斯波克:《星际迷航》主角之一。 蜥

    2024年02月09日
    浏览(37)
  • NOIP2013普及组复赛T4:车站分级

    题目链接:洛谷P1983 [NOIP2013 普及组] 车站分级 一条单向的铁路线上,依次有编号为 1 , 2 , … , n 1, 2, …, n 1 , 2 , …

    2024年02月08日
    浏览(34)
  • Bessie Come Home回家 NOIP题解

    Bessie Come Home 回家 (comehome.pas) 【问题描述】 现在是晚餐时间,而母牛们在外面分散的牧场中。农民约翰按响了电铃,所以她们开始向谷仓走去。你的工作是要指出哪只母牛会最先到达谷仓(在给出的测试数据中,总会有且只有一只最快的母牛)。在挤奶的时候(晚餐前),每只母牛都在

    2024年02月11日
    浏览(52)
  • P1077 [NOIP2012 普及组] 摆花 题解

    小明的花店新开张,为了吸引顾客,他想在花店的门口摆上一排花,共 m m m 盆。通过调查顾客的喜好,小明列出了顾客最喜欢的 n n n 种花,从 1 1 1 到 n n n 标号。为了在门口展出更多种花,规定第 i i i 种花不能超过 a i a_i a i ​ 盆,摆花时同一种花放在一起,且不同种类的花

    2024年02月08日
    浏览(45)
  • 洛谷 P3304 [SDOI2013] 直径 题解

    题目链接 第一部分好说,求直径,dfs或者DP都可以。 第二部分,有一个定理,就是所有直径中点重叠。 那么有两种情况 一种是中点在一个节点上,那么显然这个点是每条直径的终点,也就是说直径的一半相等。从这个点出发dfs,找出所有最远点。如果只有两条,输出depth之

    2024年02月14日
    浏览(37)
  • [NOIP2003 提高组] 加分二叉树

    设一个 n 个节点的二叉树 tree 的中序遍历为(1,2,3,…,n),其中数字 1,2,3,…,n 为节点编号。每个节点都有一个分数(均为正整数),记第 i 个节点的分数为 di​,tree 及它的每个子树都有一个加分,任一棵子树 subtree(也包含 tree 本身)的加分计算方法如下: subtree 的左子

    2024年02月08日
    浏览(40)
  • P1012 [NOIP1998 提高组] 拼数

    设有 �n 个正整数 �1…��a1​…an​,将它们联接成一排,相邻数字首尾相接,组成一个最大的整数。 第一行有一个整数,表示数字个数 �n。 第二行有 �n 个整数,表示给出的 �n 个整数 ��ai​。 一个正整数,表示最大的整数 输入 #1 复制 输出 #1 复制 输入 #

    2023年04月08日
    浏览(34)
  • NOIP2003提高组T1:神经网络

    [NOIP2003 提高组] 神经网络 人工神经网络(Artificial Neural Network)是一种新兴的具有自我学习能力的计算系统,在模式识别、函数逼近及贷款风险评估等诸多领域有广泛的应用。对神经网络的研究一直是当今的热门方向,兰兰同学在自学了一本神经网络的入门书籍后,提出了一

    2024年01月23日
    浏览(34)
  • P1013 [NOIP1998 提高组] 进制位

    著名科学家卢斯为了检查学生对进位制的理解,他给出了如下的一张加法表,表中的字母代表数字。 例如: 其含义为: �+�=�L+L=L,�+�=�L+K=K,�+�=�L+V=V,�+�=�L+E=E �+�=�K+L=K,�+�=�K+K=V,�+�=�K+V=E,�+�=��K+E=KL ⋯⋯ �+�=��E+E=KV 根据这些规则可推

    2023年04月08日
    浏览(34)
  • P1039 [NOIP2003 提高组] 侦探推理

    明明同学最近迷上了侦探漫画《柯南》并沉醉于推理游戏之中,于是他召集了一群同学玩推理游戏。游戏的内容是这样的,明明的同学们先商量好由其中的一个人充当罪犯(在明明不知情的情况下),明明的任务就是找出这个罪犯。接着,明明逐个询问每一个同学,被询问者

    2023年04月26日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包