zoukankan      html  css  js  c++  java
  • UPC-5909 货物运输(LCA最近公共祖先维护路径最小权)

    题目描述
    在一片苍茫的大海上,有n座岛屿,岛屿与岛屿之间由桥梁连接,所有的岛屿刚好被桥梁连接成一个树形结构,即共n-1架桥梁,且从任何一座岛屿出发都能到达其他任何一座岛屿。
    第i座桥梁有一个承重量wi,表示该桥梁一次性最多通过重量为wi的货物。
    现在有m个货物运输路线,第i个路线要从岛屿xi出发到达岛屿yi。为了最大化利益,你需要求出在不超过路线上任何一架桥梁的承重量的基础上,每个路线最多运输重量为多少货物。
    输入
    第一行为两个整数n,m。
    接下来n-1行,每行三个整数x,y,w,表示有一座承重量为w的桥梁连接岛屿x和y。
    接下来m行,每行两个整数x,y,表示有一条从岛屿x出发到达岛屿y的路线,保证x≠y。
    输出
    输出共m行,每行一个整数,第i个整数表示第i条路线的最大重量。
    样例输入
    6 5
    1 2 2
    2 3 5
    2 4 2
    2 5 3
    5 6 1
    2 4
    6 2
    1 3
    3 5
    1 6
    样例输出
    2
    1
    2
    3
    1
    提示
    岛屿间连接情况如图所示:

    2,4间只有一架桥,该路线最大运输重量为2
    6,2间有两架桥,承重分别为3和1,该路线最大运输重量为1
    剩余询问不再作解释

    对于50%的数据n,m<=2000
    对于100%的数据 n,m<=100000,w<=10^9

    因为题目表明是一棵树,因此从一个节点到达另一个节点只有唯一一条路,要求路径上的最小权值,那么只需要跑一边LCA最近公共祖先的基础上维护路径最小权即可,甚至不用倍增法优化,不过听说是因为数据较水没有卡朴素暴力。

    关于建图,因为题目中输入时没有说明具体哪边是父亲哪边是儿子,也没有定义根节点,因为其总体是一棵树,因此设任意一个节点拎起来都是一棵树,默认一个节点为根节点,剩下的都作为儿子即可,边权也作为儿子的属性。这样在输入时,如果一个节点有父亲,那么另一个节点就做儿子,如果两个节点都没有父亲,默认x左边输入的节点作为父亲,不会存在一个孩子有多个父亲的情况。因为一旦有父亲就不会再次作为儿子被赋值,而是让另一个节点做儿子。

    代码如下:

    #include<stdio.h>///LCA最近公共祖先朴素算法
    #include<string.h>
    #include<algorithm>
    using namespace std;
    int fa[100005];
    int val[100005];
    int deep(int x)
    {
        int cnt=0;
        while(x)
        {
            cnt++;
            x=fa[x];
        }
        return cnt;
    }
    int main()
    {
        int n,m;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            int x,y,w;
            memset(fa,0,sizeof(fa));
            for(int i=0;i<n-1;i++)
            {
                scanf("%d%d%d",&x,&y,&w);///关于建图,因为题目没有给出父子关系,也没有先后顺序
                if(fa[x]!=0)fa[y]=x,val[y]=w;///因此判断双方是否有父亲即可,如果都没有父亲默认x作父亲
                else fa[x]=y,val[x]=w;
            }
            while(m--)
            {
                scanf("%d%d",&x,&y);
                int dx=deep(x),dy=deep(y);
                int minx=0x7fffffff,miny=0x7fffffff;///只需在回溯时不断维护当前最小权
                if(dx<dy)
                {
                    int tt=dy-dx;
                    while(tt--)
                    {
                        miny=min(miny,val[y]);///注意先取最小权再向上回溯
                        y=fa[y];
                    }
                }
                else if(dx>dy)
                {
                    int tt=dx-dy;
                    while(tt--)
                    {
                        minx=min(minx,val[x]);
                        x=fa[x];
                    }
                }
                while(x!=y)///每次回溯都先取最小权
                {
                    minx=min(minx,val[x]);
                    x=fa[x];
                    miny=min(miny,val[y]);
                    y=fa[y];
                }
                printf("%d
    ",min(minx,miny));
            }
        }
    }
    
  • 相关阅读:
    高德地图信息窗体轮播及多组坐标点添加
    移动端适配及px转rem
    css伪类样式覆盖
    vue-amap-marker相关问题,信息窗体及自定义图片的偏移问题
    echart自定义图例样式及统计图颜色相关
    ts学习笔记[枚举类型]
    从面试中查漏补缺
    百度编译器插入自定义内容和样式(转)
    .net的母版页相关
    几种Position属性的用法
  • 原文地址:https://www.cnblogs.com/kuronekonano/p/11135830.html
Copyright © 2011-2022 走看看