• bzoj3732 Network(NOIP2013 货车运输)


    Description

    给你N个点的无向图 (1 <= N <= 15,000),记为:1…N。 
    图中有M条边 (1 <= M <= 30,000) ,第j条边的长度为: d_j ( 1 < = d_j < = 1,000,000,000).

    现在有 K个询问 (1 < = K < = 20,000)。 
    每个询问的格式是:A B,表示询问从A点走到B点的所有路径中,最长的边最小值是多少?

    Input

    第一行: N, M, K。 
    第2..M+1行: 三个正整数:X, Y, and D (1 <= X <=N; 1 <= Y <= N). 表示X与Y之间有一条长度为D的边。 
    第M+2..M+K+1行: 每行两个整数A B,表示询问从A点走到B点的所有路径中,最长的边最小值是多少?

    Output

     对每个询问,输出最长的边最小值是多少。

    Sample Input

    6 6 8
    1 2 5
    2 3 4
    3 4 3
    1 4 8
    2 5 7
    4 6 2
    1 2
    1 3
    1 4
    2 3
    2 4
    5 1
    6 2
    6 1

    Sample Output

    5
    5
    5
    4
    4
    7
    4
    5

    HINT

    1 <= N <= 15,000 

    1 <= M <= 30,000 

    1 <= d_j <= 1,000,000,000 

    1 <= K <= 15,000

    最小生成树+倍增求lca

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    const int maxn=15000+10,maxm=30000+10;
    int n,m,k,faf[maxn],tot;
     
    struct Node{
        int x,y,d;
        bool operator <(const Node& b) const{return d<b.d;}
    }node[maxm];
     
    int aa;char cc;
    int read() {
        aa=0;cc=getchar();
        while(cc<'0'||cc>'9') cc=getchar();
        while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
        return aa;
    }
     
    int find(int x) {
        return faf[x]==x? x:faf[x]=find(faf[x]);
    }
     
    int fir[maxn],to[2*maxn],nxt[2*maxn],val[2*maxn],e=0;
    void add(int x,int y,int z) {
        to[++e]=y;nxt[e]=fir[x];fir[x]=e;val[e]=z;
        to[++e]=x;nxt[e]=fir[y];fir[y]=e;val[e]=z;
    }
     
    int dep[maxn],fa[maxn][20],ans[maxn][20];
    void dfs(int pos,int h) {
        dep[pos]=h;
        for(int y=fir[pos];y;y=nxt[y]) {
            if(to[y]==fa[pos][0]) continue;
            fa[to[y]][0]=pos;
            ans[to[y]][0]=val[y];
            dfs(to[y],h+1);
        }
    }
     
    int mi[20],cha,rs;
    int LCA(int x,int y) {
        rs=1;
        if(dep[x]!=dep[y]) {
            if(dep[x]<dep[y]) swap(x,y);
            cha=dep[x]-dep[y];
            for(int i=tot;i>=0;--i) if(cha>=mi[i]) {
                rs=max(rs,ans[x][i]);
                cha-=mi[i]; x=fa[x][i];
                if(!cha) break;
            }
        }
        int xx,yy,d;
        while(x!=y) {
            xx=x;yy=y;d=-1;
            while(xx!=yy) {
                if(d>=0) rs=max(rs,ans[x][d]),rs=max(rs,ans[y][d]);
                x=xx;y=yy;
                xx=fa[x][++d]; yy=fa[y][d];
            }
            if(d==0) rs=max(rs,ans[x][d]),rs=max(rs,ans[y][d]),x=xx,y=yy;
        }
        return rs;
    }
     
    int main() {
        n=read();m=read();k=read();
        int a,b;
        for(int i=1;i<=m;++i) {
            node[i].x=read();node[i].y=read();node[i].d=read();
        }
        sort(node+1,node+m+1);
        for(int i=1;i<=n;++i) faf[i]=i;
        for(int i=1;i<=m;++i) {
            a=find(node[i].x);b=find(node[i].y);
            if(a!=b) {
                faf[a]=b;tot++;
                add(node[i].x,node[i].y,node[i].d);
            }
            if(tot==n-1) break;
        }
        dfs(1,1); tot=-1;
        for(int i=1;i<n*2;i<<=1) mi[++tot]=i;
        for(int i=1;i<=tot;++i) for(int j=1;j<=n;++j) {
            fa[j][i]=fa[fa[j][i-1]][i-1];
            ans[j][i]=max(ans[j][i-1],ans[fa[j][i-1]][i-1]);
        }
        for(int i=1;i<=k;++i) {
            a=read();b=read();
            printf("%d
    ",LCA(a,b));
        }
        return 0;
    }
    

      

    弱者就是会被欺负呀
  • 相关阅读:
    Cesium视角
    Cesium删除特定的实体
    cesium之CLAMPED
    JavaScript:使用setAttribute()改变网页中标签的onclick属性
    atoi()函数及其实现
    寻找数组中的第二大数
    字符串函数之strcpy
    互换两个变量(不使用中间变量)
    寻找兄弟单词(2012.5.6百度实习)
    大数据量的存储分表常见算法(转)
  • 原文地址:https://www.cnblogs.com/Serene-shixinyi/p/7545182.html
Copyright © 2020-2023  润新知