• NOIP2013 货车运输 倍增


    问题描述

    A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。

    输入描述

    第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道路。
    接下来 m 行每行 3 个整数 x、y、z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z 的道路。注意:x 不等于 y,两座城市之间可能有多条道路。
    接下来一行有一个整数 q,表示有 q 辆货车需要运货。
    接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意:x 不等于 y。

    输出描述

    输出共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货车不能到达目的地,输出-1。

    题解:

    首先易得货车可以通过的权值最小的道路一定是在这个图的最大生成树中的。所以先用kruskal算一下最大生成树,将这个最大生成树再存一个图,起点和重点的连通性可以通过并查集来判断。

    然后在这个最大生成树上找这两个点的lca,找到这个两个点之间的最小值,就是货车的最大载货量。

    #include<bits/stdc++.h>
    using namespace std;
    #define maxn 10005
    #define inf 0x7ffffff 
    int n,m,q,cnt;
    int deep[maxn],f[maxn],fa[maxn][17],d[maxn][17];
    bool vis[maxn];
    struct edge{
        int u,v,w;
    }e[50005];
    int head[maxn];
    struct node{
        int next,to,k;
    }a[20001];
    void insert(int u,int v,int w){
        cnt++;
        a[cnt].next=head[u];a[cnt].to=v;a[cnt].k=w;
        head[u]=cnt;
    }
    bool cmp(edge a,edge b){
        return a.w>b.w;
    }
    void dfs(int x){
        vis[x]=1;
        for(int i=1;i<=16;i++){
            if(deep[x]<(1<<i))break;
            fa[x][i]=fa[fa[x][i-1]][i-1];
            d[x][i]=min(d[x][i-1],d[fa[x][i-1]][i-1]);
        }
        for(int i=head[x];i;i=a[i].next){
            int s=a[i].to;
            if(vis[s])continue;
            fa[s][0]=x;
            d[s][0]=a[i].k;
            deep[s]=deep[x]+1;
            dfs(s);
        }
    }
    int lca(int x,int y){
        if(deep[x]<deep[y])swap(x,y);
        int t=deep[x]-deep[y];
        for(int i=0;i<=16;i++)
        if((1<<i)&t)x=fa[x][i];
        for(int i=16;i>=0;i--){
            if(fa[x][i]!=fa[y][i]){
                x=fa[x][i];y=fa[y][i];
            }
        }
        if(x==y)return x;
        return fa[x][0];
    }
    int ask(int x,int f){
        int mn=inf;
        int t=deep[x]-deep[f];
        for(int i=0;i<=16;i++){
            if(t&(1<<i)){
                mn=min(mn,d[x][i]);
                x=fa[x][i];
            }
        }
        return mn;
    }
    int find(int x){
        if(x==f[x])return x;
        return f[x]=find(f[x]);
    }
    int main(){
        memset(d,127,sizeof d);
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)f[i]=i;
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
        }
        sort(e+1,e+m+1,cmp);
        int tot=0;
        for(int i=1;i<=m;i++){
            int p=find(e[i].u),q=find(e[i].v);
            if(p!=q){
                f[p]=q;
                insert(e[i].u,e[i].v,e[i].w);insert(e[i].v,e[i].u,e[i].w);
                tot++;
                if(tot==n-1)break;
            }
        }
        for(int i=1;i<=n;i++)if(!vis[i])dfs(i);
        scanf("%d",&q);
        for(int i=1;i<=q;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            if(find(x)!=find(y)){printf("-1
    ");continue;}
            else {
                int t=lca(x,y);
                printf("%d
    ",min(ask(x,t),ask(y,t)));
            }
        }
        return 0;
    }
  • 相关阅读:
    智能推荐算法演变及学习笔记(三):CTR预估模型综述
    从中国农业银行“雅典娜杯”数据挖掘大赛看金融行业数据分析与建模方法
    智能推荐算法演变及学习笔记(二):基于图模型的智能推荐(含知识图谱/图神经网络)
    (设计模式专题3)模板方法模式
    (设计模式专题2)策略模式
    (设计模式专题1)为什么要使用设计模式?
    关于macOS上常用操作命令(持续更新)
    记录下关于RabbitMQ常用知识点(持续更新)
    EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.
    SpringCloud教程二:Ribbon(Finchley版)
  • 原文地址:https://www.cnblogs.com/Elfish/p/7717324.html
Copyright © 2020-2023  润新知