zoukankan      html  css  js  c++  java
  • 【LCA&倍增】货物运输 @upcexam5909

    时间限制: 1 Sec 内存限制: 128 MB
    题目描述
    在一片苍茫的大海上,有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

    来源
    2018山东冬令营
    http://exam.upc.edu.cn/problem.php?id=5909

    思路
    第一次写倍增求LCA
    这一题每次查询的两个点 x,y
    可以考虑倍增求这两个点的LCA
    用g[i][j]表示从i到i的第2^j个祖先的所经过的路的最小权值
    维护时 g[i][j]=min( g[i][j-1] , g[ f[i][j-1] ][j-1] )
    当x或y向根节点移动时,将对应路径上的最小值与答案取min

    代码

    #define FILE() freopen("../../in.txt","r",stdin)
    #include <bits/stdc++.h>
    
    using namespace std;
    const int maxn = 100005;
    const int maxl = 20;
    const int INF = 0x3f3f3f3f;
    int anc[maxn][maxl],fa[maxn],deep[maxn],n,m,cnt,head[maxn];//anc记录祖先,fa记录父亲节点,deep记录深度
    int g[maxn][maxl];
    
    struct edge{
        int v,w,nex;
    }ed[maxn*2];
    
    void addedge(int u,int v,int w){
        cnt++;
        ed[cnt].v = v;
        ed[cnt].w = w;
        ed[cnt].nex = head[u];
        head[u] = cnt;
    }
    
    void dfs(int x){
        anc[x][0] = fa[x];
        for(int i=1;i<maxl;i++){
            anc[x][i] = anc[anc[x][i-1]][i-1];
            g[x][i] = min(g[x][i-1],g[anc[x][i-1]][i-1]); //
        }
        for(int i=head[x];i;i=ed[i].nex){
            if(ed[i].v!=fa[x]){
                int y = ed[i].v;
                fa[y] = x;
                deep[y] = deep[x]+1;
                g[y][0] = ed[i].w; //
                dfs(y);
            }
        }
    }
    
    int lca(int x,int y){
        int ret = INF;
        if(deep[x]<deep[y])swap(x,y);
        for(int i=maxl-1;i>=0;i--){
            if(deep[y]<=deep[anc[x][i]]){
                ret = min(ret,g[x][i]);
                x = anc[x][i];
            }
        }
    //    if(x==y)return x;
        for(int i=maxl-1;i>=0;i--){
            if(anc[x][i]!=anc[y][i]){
                ret = min(ret,g[x][i]);
                ret = min(ret,g[y][i]);
                x = anc[x][i];
                y = anc[y][i];
            }
        }
        if(x!=y){
            ret = min(ret,g[x][0]);
            ret = min(ret,g[y][0]);
        }
        return ret;
    }
    
    int main() {
    //    FILE();
        cin>>n>>m;
        for(int i=0;i<n-1;i++){
            int from,to,value;
            scanf("%d%d%d",&from,&to,&value);
            addedge(from,to,value);
            addedge(to,from,value);
        }
        for(int i=0;i<n;i++){
            for(int j=0;j<maxl;j++){
                g[i][j] = INF;
            }
        }
        dfs(1);
        for(int i=0;i<m;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            printf("%d
    ",lca(x,y));
        }
        return 0;
    }
  • 相关阅读:
    CentOS 6.7 如何启用中文输入法
    10w数组去重,排序,找最多出现次数(精华)
    win10虚拟机搭建Hadoop集群(已完结)
    Linux常用命令
    调用接口显示Required request body is missing
    Git 的使用
    Navicat创建事件,定时更新数据库
    mysql生成UUID
    时间戳与字符串相互转换
    牛客中的错题
  • 原文地址:https://www.cnblogs.com/NeilThang/p/9356629.html
Copyright © 2011-2022 走看看