zoukankan      html  css  js  c++  java
  • P1967 货车运输

    题目描述

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

    输入输出格式

    输入格式:

     

    输入文件名为 truck.in。

    输入文件第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道

    路。 接下来 m 行每行 3 个整数 x、 y、 z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z 的道路。注意: x 不等于 y,两座城市之间可能有多条道路 。

    接下来一行有一个整数 q,表示有 q 辆货车需要运货。

    接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意: x 不等于 y 。

     

    输出格式:

     

    输出文件名为 truck.out。

    输出共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货

    车不能到达目的地,输出-1。

     

    输入输出样例

    输入样例#1:
    4 3
    1 2 4
    2 3 3
    3 1 1
    3
    1 3
    1 4
    1 3
    输出样例#1:
    3
    -1
    3

    说明

    对于 30%的数据,0 < n < 1,000,0 < m < 10,000,0 < q< 1,000;

    对于 60%的数据,0 < n < 1,000,0 < m < 50,000,0 < q< 1,000;

    对于 100%的数据,0 < n < 10,000,0 < m < 50,000,0 < q< 30,000,0 ≤ z ≤ 100,000。

    题目大意:求两点之间路径上最短边的最大值。

    题解:

    方法一、Kruskal建最大生成树+倍增lca

    方法二、Kruskal建最大生成树+树链剖分

    方法三、Kruskal重构树+树剖求lca

    代码

    一、黄学长的

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #define inf 0x7fffffff
    using namespace std;
    int n,m,q,cnt,tot,deep[10001],head[10001],f[10001],fa[10001][17],d[10001][17];
    bool vis[10001];
    struct edge{int x,y,v;}a[50001];
    struct e{int next,to,v;}e[20001];
    void ins(int u,int v,int w)
    {e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;e[cnt].v=w;}
    void insert(int u,int v,int w)
    {ins(u,v,w);ins(v,u,w);}
    int find(int x)
    {return f[x]==x?x:f[x]=find(f[x]);}
    bool cmp(edge a,edge b)
    {return a.v>b.v;}
    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=e[i].next)
        {
            if(vis[e[i].to])continue;
            fa[e[i].to][0]=x;
            d[e[i].to][0]=e[i].v;
            deep[e[i].to]=deep[x]+1;
            dfs(e[i].to);
        }
    }
    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 main()
    {
        memset(d,127/3,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",&a[i].x,&a[i].y,&a[i].v);
        sort(a+1,a+m+1,cmp);
        for(int i=1;i<=m;i++)
        {
            int x=a[i].x,y=a[i].y;
            int p=find(a[i].x),q=find(a[i].y);
            if(p!=q)
            {
                f[p]=q;
                insert(x,y,a[i].v);
                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;
    }

    二、

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #define maxn 50005
    #define inf 0x7fffffff
    using namespace std;
    int n,m,sumedge,cnt,q;
    int head[maxn],fe[maxn],deep[maxn],wson[maxn],top[maxn];
    int fa[maxn],size[maxn],dad[maxn],real[maxn],tpos[maxn];
    struct Edge{
        int x,y,z,nxt;
        Edge(int x=0,int y=0,int z=0,int nxt=0):
            x(x),y(y),z(z),nxt(nxt){}
    }edge[maxn<<1];
    
    struct E{
        int x,y,z;
    //    bool operator < (const E &x)const {return z>x.z;}
    }e[maxn];
    
    void add(int x,int y,int z){
        edge[++sumedge]=Edge(x,y,z,head[x]);
        head[x]=sumedge;
    }
    
    struct Tree{
        int l,r,maxv,minv;
    }tr[maxn<<2];
    
    int f(int x){
        return fa[x]==x?x:fa[x]=f(fa[x]);
    }
    bool cmp(E a,E b){
        return a.z>b.z;
    }
    void Kruskal(){
        sort(e+1,e+m+1,cmp);
        int tot=0;
        for(int i=1;i<=m;i++){
            int fx=f(e[i].x),fy=f(e[i].y);
            if(fx!=fy){
                fa[fx]=fy;
                add(e[i].x,e[i].y,e[i].z);
                add(e[i].y,e[i].x,e[i].z);
                if(++tot==n-1)break;
            }
        }
    }
    void dfs1(int x,int fu){
        size[x]=1;
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(v==fu)continue;
            dad[v]=x;fe[v]=edge[i].z;deep[v]=deep[x]+1;
            dfs1(v,x);
            size[x]+=size[v];
            if(size[v]>size[wson[x]])wson[x]=v;
        }
    }
    void dfs2(int x,int fr){
        tpos[x]=++cnt;real[cnt]=x;top[x]=fr;
        if(wson[x])dfs2(wson[x],fr);
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(v!=dad[x]&&v!=wson[x])dfs2(v,v);
        }
    }
    
    void pushup(int rt){
        tr[rt].maxv=max(tr[rt<<1].maxv,tr[rt<<1|1].maxv);
        tr[rt].minv=min(tr[rt<<1].minv,tr[rt<<1|1].minv);
        return;
    }
    
    void build(int rt,int l,int r){
        tr[rt].l=l;tr[rt].r=r;
        if(l==r){
            tr[rt].minv=tr[rt].maxv=fe[real[l]];
            return ;
        }
        int mid=(l+r)>>1;
        build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);
        pushup(rt);
    }
    
    /*int query_min(int rt,int l,int r,int ql,int qr){
        if(l>r)return 2147483647;
        if(ql<=l&&r<=qr){
            return tr[rt].minv;
        //    cout<<"lalal  "<<tr[rt].minv<<endl;
        }
        int mid=(l+r)>>1;ans=inf;
        if(qr<=mid)return query_min(rt<<1,l,mid,ql,qr);
        else if(ql>mid)return query_min(rt<<1|1,mid+1,r,ql,qr);
        else return min(query_min(rt<<1,l,mid,ql,qr),query_min(rt<<1|1,mid+1,r,ql,qr));
    
        if (ql<=mid)return query_min(rt<<1,l,mid,ql,qr);
        if (qr>mid)return query_min(rt<<1|1,mid+1,r,ql,qr);
    }
    */
    int query_min(int o,int l,int r,int ql,int qr){
        if (l>r) return 2147483647;
        int mid=(l+r)/2,ans=inf;
        if (ql<=l&&r<=qr)return tr[o].minv;
        if (ql<=mid)ans=min(ans,query_min(o*2,l,mid,ql,qr));
        if (qr>mid)ans=min(ans,query_min(o*2+1,mid+1,r,ql,qr));
        //pushup(o);
        return ans;
    }
    int qmin(int u,int v){
        int ans=inf;
        while(top[u]!=top[v]){
            if(deep[top[u]]>deep[top[v]])swap(u,v);
            ans=min(ans,query_min(1,1,n,tpos[top[v]],tpos[v]));
            v=dad[top[v]];
        }
        if(deep[u]>deep[v])swap(u,v);
        ans=min(ans,query_min(1,1,n,tpos[u]+1,tpos[v]));
    }
    int main(){
        memset(fe,-1,sizeof(fe));//**
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z);
        for(int i=1;i<=n;i++)fa[i]=i;
        Kruskal();
        dfs1(1,0);
        dfs2(1,1);
        build(1,1,n);
        scanf("%d",&q);
        while(q--){
            int x,y;
            scanf("%d%d",&x,&y);
            if(f(x)!=f(y))printf("-1
    ");
            else printf("%d
    ",qmin(x,y));
        }
        return 0;
    }

    三、

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define maxm 500008
    #define maxn 100008
    
    using namespace std;
    
    int n,m,x,y,z,tot,sumedge,nn,q;
    int head[maxn],fa[maxn],size[maxn],dad[maxn],top[maxn],deep[maxn],w[maxn];
    
    struct E{
        int x,y,z;
    ///    bool operator < (const E &a)const{return z>a.z;}
    }e[maxm];
    
    struct Edge{
        int x,y,nxt;
        Edge(int x=0,int y=0,int nxt=0):
            x(x),y(y),nxt(nxt){}
    }edge[maxn<<1];
    
    void add(int x,int y){
        edge[++sumedge]=Edge(x,y,head[x]);
        head[x]=sumedge;
    }
    
    bool cmp(E a,E b){return a.z>b.z;}
    
    int f(int x){return fa[x]==x?x:fa[x]=f(fa[x]);}
    
    void dfs(int x){
        size[x]=1;deep[x]=deep[dad[x]]+1;
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(v!=dad[x]){
                dad[v]=x;
                dfs(v);
                size[x]+=size[v];
            }
        }
    }
    
    void dfs2(int x){
        int s=0;
        if(!top[x])top[x]=x;
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(v!=dad[x]&&size[v]>size[s])s=v;
        }
        if(s){
            top[s]=top[x];
            dfs2(s);
        }
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(v!=dad[x]&&v!=s)dfs2(v);
        }
    }
    
    int lca(int x,int y){
        for(;top[x]!=top[y];){
            if(deep[top[x]]>deep[top[y]])
            swap(x,y);
            y=dad[top[y]];
        }
        if(deep[x]>deep[y])swap(x,y);
        return w[x];
    }
    
    int main(){
        scanf("%d%d",&n,&m);nn=n;
        for(int i=1;i<=m;i++)scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z);
        for(int i=1;i<=n;i++)fa[i]=i;
        sort(e+1,e+m+1,cmp);
        for(int i=1;i<=m;i++){
            int fx=f(e[i].x),fy=f(e[i].y);
            if(fx!=fy){
                nn++;
                add(nn,fx);add(fx,nn);
                add(fy,nn);add(nn,fy);
                fa[nn]=nn;fa[fx]=nn;fa[fy]=nn;
                ++tot;w[nn]=e[i].z;
                if(tot==n-1)break;
            }
        }
        dfs(nn);dfs2(nn);
        scanf("%d",&q);
        for(int i=1;i<=q;i++){
            scanf("%d%d",&x,&y);
            if(f(x)!=f(y)){
                printf("-1
    ");
                continue;
            }
            printf("%d
    ",lca(x,y));
        }
        return 0;
    }
  • 相关阅读:
    JeecgBoot 2.4 微服务正式版发布,基于SpringBoot的低代码平台
    JeecgBoot 常见问题Q&A
    docker安装rabbitmq延时队列插件
    docker安装nacos
    docker安装xxl-job-admin
    docker安装rabbitmq
    低代码开发平台有哪些?
    对比 jeecgboot 和国内外其它低代码平台的区别
    JimuReport积木报表 — API数据源报表带参制作
    JimuReport积木报表 — API数据源报表制作
  • 原文地址:https://www.cnblogs.com/zzyh/p/7503164.html
Copyright © 2011-2022 走看看