zoukankan      html  css  js  c++  java
  • 【noip2013】【BZOJ3732】 货车运输/network [生成树kruskal LCA ]

    P1967 货车运输

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

    最大生成树就是kruskal时将边改为降序 然后就和普通kruskal一样

    然后就是用的LCA倍增模板中说的其它骚操作一样

    可以在预处理的时候还可以顺便记录下这段路径的权值最大值 最小值或者权值和之类的信息,这样就可以在O(logn)的时间内求出树上两点间路径权值的最大值、最小值还有权值和

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #include<cmath>
    #include<stack>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define rg register
    const int N=100000+5,M=500000+5,inf=0x3f3f3f3f,P=19650827;
    int n,m,q;
    int dep[N],p[N][25],w[N][25];
    template <class t>void rd(t &x){
        x=0;int w=0;char ch=0;
        while(!isdigit(ch)) w|=ch=='-',ch=getchar();
        while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        x=w?-x:x;
    }
    
    int head[N],tot=0,ans;
    struct edge{int v,nxt,w;}e[M];
    void add(int u,int v,int w){
        e[++tot]=(edge){v,head[u],w};head[u]=tot;
    }
    
    int f[N];
    struct node{
        int u,v,w;
    }nd[M];
    bool cmp(node a,node b){return a.w>b.w;}
    int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
    void kruskal(){
        int cnt=0;
        for(rg int i=1;i<=n;++i) f[i]=i;
        for(rg int i=1,u,v,w;i<=m;++i){
            u=nd[i].u,v=nd[i].v,w=nd[i].w;
            if(find(u)!=find(v)){
                f[f[u]]=f[v];
                ++cnt;
                add(u,v,w),add(v,u,w);
                if(cnt==n-1) break;
            }
        }
    }
    
    void dfs(int u){
        for(int i=head[u],v;i;i=e[i].nxt){
            v=e[i].v;
            if(!dep[v]){//未走过 
                dep[v]=dep[u]+1;
                p[v][0]=u;
                w[v][0]=e[i].w;
                dfs(v);
            }
        }
    }
    void build(){
        for(rg int i=1;i<=n;++i){
            if(!dep[i]){
                dep[i]=1;
                p[i][0]=0;
                dfs(i);
            }
        }
        dfs(1);//连起来
        for(int i=1; i<=20; i++)
            for(int j=1; j<=n; j++){
                p[j][i]=p[p[j][i-1]][i-1]; 
                w[j][i]=min(w[j][i-1], w[p[j][i-1]][i-1]);
            }
    }
    
    int LCA(int a,int b){
        ans=inf;
        if(dep[a]>dep[b]) swap(a,b);
        for(int i=20;i>=0;--i){
            if(dep[p[b][i]]<dep[a]) continue;
            ans=min(ans,w[b][i]);b=p[b][i];
        }
        if(a==b) return ans;
        for(int i=20;i>=0;--i){
            if(p[a][i]==p[b][i]) continue;
            ans=min(ans,min(w[a][i],w[b][i]));
            a=p[a][i],b=p[b][i];
        }
        ans=min(ans,min(w[a][0],w[b][0]));
        return ans;
    }
    
    int main(){
        //freopen("in.txt","r",stdin);
        memset(dep,0,sizeof(dep));
        memset(p,0,sizeof(p));
        rd(n),rd(m);
            int u,v,w;
        for(rg int i=1;i<=m;++i){
            rd(u),rd(v),rd(w);
            nd[i]=(node){u,v,w};
        }
        sort(nd+1,nd+1+m,cmp);
        kruskal();
        build();
        rd(q);
        for(rg int i=1;i<=q;++i){
            rd(u),rd(v);
            if(find(u)!=find(v)) printf("-1
    ");
            else printf("%d
    ",LCA(u,v));
        }
        return 0;
    }

    BZOJ3732

     淦 一样并且还更简单的题我居然打了一晚上我的天

    使生成树中任意点A到B的路径上最长边最小

    k次询问A到B路径上的最长边长度

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define Max(X,Y) ((X)>(Y)?(X):(Y))
    #define Abs(x) ((x)<0?(-x):(x))
    typedef pair<int,int>pii;
    const int N=15000+5,M=3e4+5,inf=0x3f3f3f3f;
    int n,m,k;
    template<class t>void rd(t &x){
        x=0;int w=0;char ch=0;
        while(!isdigit(ch)) w|=ch=='-',ch=getchar();
        while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        x=w?-x:x;
    }
    
    struct Edge{
        int u,v,w;
        bool operator<(const Edge&A)const{return w<A.w;}
    }E[M];
    int head[N],tot=0;
    struct edge{int v,w,nxt;}e[N<<1];
    void add(int u,int v,int w){
        e[++tot]=(edge){v,w,head[u]},head[u]=tot;
    }
    
    int f[N];
    int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
    void kruskal(){
        for(int i=1;i<=n;++i) f[i]=i;
        for(int i=1,u,v,w;i<=m;++i){
            if(tot==(n-1)<<1) return;
            u=E[i].u,v=E[i].v,w=E[i].w;
            if(find(u)!=find(v)) f[f[u]]=f[v],add(u,v,w),add(v,u,w);
        }
    }
    
    int dep[N],fa[N][30],mx[N][30];
    void dfs(int u,int ff){
        fa[u][0]=ff;
        for(int i=head[u],v;i;i=e[i].nxt){
            v=e[i].v;
            if(v==ff) continue;
            dep[v]=dep[u]+1,mx[v][0]=e[i].w,dfs(v,u);
        }
    }
    void build(){
        dfs(1,0);
        for(int i=1;i<=20;++i)
        for(int j=1;j<=n;++j)
        fa[j][i]=fa[fa[j][i-1]][i-1],
        mx[j][i]=Max(mx[fa[j][i-1]][i-1],mx[j][i-1]);
    }
    
    int query(int a,int b){
        int ans=0;
        if(dep[a]>dep[b]) swap(a,b);
        for(int i=20;i>=0;--i)
        if(dep[fa[b][i]]>=dep[a]) ans=Max(ans,mx[b][i]),b=fa[b][i];
        if(a==b) return  ans;
        for(int i=20;i>=0;--i)
        if(fa[a][i]!=fa[b][i]) ans=Max(ans,Max(mx[a][i],mx[b][i])),a=fa[a][i],b=fa[b][i];
        return Max(ans,Max(mx[a][0],mx[b][0])); 
    }
    
    int main(){
        freopen("2.in","r",stdin);
        rd(n),rd(m),rd(k);
        for(int i=1;i<=m;++i) rd(E[i].u),rd(E[i].v),rd(E[i].w);
        sort(E+1,E+m+1);
        kruskal();
        memset(dep,0,sizeof(dep));
        build();
        while(k--){
            int xx,yy;rd(xx),rd(yy);
            printf("%d
    ",query(xx,yy));
        }
        return 0;
    } 
  • 相关阅读:
    最全的“大数据”学习资源
    民生银行十五年的数据体系建设,深入解读阿拉丁大数据生态圈、人人BI 是如何养成的?【转】
    大数据分析界的“神兽”Apache Kylin有多牛?【转】
    大数据环境下互联网行业数据仓库/数据平台的架构之漫谈-续【转】
    写给大数据开发初学者的话5[转]
    唯品会海量实时OLAP分析技术升级之路
    大数据学习笔记
    元数据
    数据仓库之数据模型
    官方教程:Apache Kylin和Superset集成,使用开源组件,完美打造OLAP系统
  • 原文地址:https://www.cnblogs.com/lxyyyy/p/10960467.html
Copyright © 2011-2022 走看看