zoukankan      html  css  js  c++  java
  • [luogu1967]货车运输

    货车运输


    Description

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

    Input

    输入文件名为 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 。

    Output
    -输出文件名为 truck.out。

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

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

    Sample Input

    4 3
    1 2 4
    2 3 3
    3 1 1
    3
    1 3
    1 4
    1 3

    Sample Output

    3
    -1
    3

    Hint

    对于 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。

    题解

    在最大生成树上树链剖分,用并查集判断是否可达

    #include <algorithm>
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    typedef long long LL;
    
    const int infty=1<<29;
    int N,M,Q;
    struct edge
    {
        int to,nxt,cost;
    }g[200050];
    struct data
    {
        int u,v,w;
    }e[500050];
    struct segmentnode
    {
        int mn;
    }seg[400050];
    int ecnt,head[100050];
    int bel[100050];
    int vis[100050],val[100050];
    int place;
    int parent[100050],deep[100050],sz[100050],tid[100050],top[100050],rnk[100050];
    
    inline void addedge(int u,int v,int w)
    {
        g[ecnt]=(edge){v,head[u],w},head[u]=ecnt++;
        g[ecnt]=(edge){u,head[v],w},head[v]=ecnt++;
    }
    
    int comp(const data & a, const data & b){return a.w>b.w;}
    
    int findset(int a){return a==bel[a]?a:bel[a]=findset(bel[a]);}
    
    void kruskal()
    {
        sort(e+1,e+M+1,comp);
        for(int i=1;i<=M;i++)bel[i]=i;
        for(int i=1;i<=M;i++)
        {
            int u=e[i].u,v=e[i].v,w=e[i].w;
            if(findset(u)==findset(v))continue;
            bel[findset(u)]=findset(v);
            addedge(u,v,w);
        }
    }
    
    void dfs(int root)
    {
        vis[root] = 1;
        for(int i=head[root];~i;i=g[i].nxt)
        {
            int v=g[i].to;if(vis[v])continue;
            dfs(v);
        }
    }
    
    void getdeep(int root,int step,int fa)
    {
        parent[root]=fa,deep[root]=step,sz[root]=1;
        for(int i=head[root];~i;i=g[i].nxt)
        {
            int v=g[i].to,w=g[i].cost;
            if(v == fa)continue;
            getdeep(v,step+1,root);
            sz[root]+=sz[v],val[v]=w;
        }
    }
    
    void devide(int root,int chain,int fa)
    {
        top[root]=chain,tid[root]=++place,rnk[place]=root;
        int k=0;
        for(int i=head[root];~i;i=g[i].nxt)
        {
            int v=g[i].to;if(v==fa)continue;
            if(sz[v]>sz[k])k=v;
        }if(k==0)return;devide(k,chain,root);
        for(int i=head[root];~i;i=g[i].nxt)
        {
            int v=g[i].to;if(v==fa||v==k)continue;
            devide(v,v,root);
        }
    }
    
    inline void pushup(int root)
    {
        seg[root].mn=min(seg[root<<1].mn,seg[root<<1|1].mn);
    }
    
    void build(int root,int l,int r)
    {
        if(l==r){seg[root].mn=val[rnk[l]];return;}
        int mid=(l+r)>>1;
        build(root<<1,l,mid),build(root<<1|1,mid+1,r);
        pushup(root);
    }
    
    int getmin(int root,int l,int r,int a,int b)
    {
        if(l==a&&r==b)return seg[root].mn;
        int mid=(l+r)>>1;
        if(b<=mid)return getmin(root<<1,l,mid,a,b);
        else if(a>mid)return getmin(root<<1|1,mid+1,r,a,b);
        else return min(getmin(root<<1,l,mid,a,mid),getmin(root<<1|1,mid+1,r,mid+1,b));
    }
    
    int getmin(int a,int b)
    {
        int res=infty;
        while(top[a]!=top[b])
        {
            if(deep[top[a]]>deep[top[b]])swap(a,b);
            res=min(res,getmin(1,1,N+1,tid[top[b]],tid[b]));
            b=parent[top[b]];
        }if(deep[a]>deep[b])swap(a,b);
        if(a!=b)res=min(res,getmin(1,1,N+1,tid[a]+1,tid[b]));
        return res;
    }
    
    int main()
    {
        while(scanf("%d%d",&N,&M)!=EOF)
        {
            memset(head,-1,sizeof(head));
            ecnt=place=0;
            for(int i=1;i<=M;i++)
            {
                scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
            }
            kruskal();
            memset(vis,0,sizeof(vis));
            deep[N+1]=1;
            for(int i=1;i<=N;i++)
            {
                if(!vis[i])
                {
                    addedge(N+1,i,infty);
                    dfs(N+1);
                }
            }
            getdeep(N+1,1,0);
            devide(N+1,N+1,0);
            build(1,1,N+1);
            scanf("%d",&Q);
            for(int i=1,u,v;i<=Q;i++)
            {
                scanf("%d%d",&u,&v);
                if(findset(u)!=findset(v))
                {
                    printf("-1
    ");
                    continue;
                }
                printf("%d
    ",getmin(u,v));
            }
        }
        return 0;
    }
    
  • 相关阅读:
    分享一些优化博客的心得
    HTTP相关整理(上)
    正则&highlight高亮实现(干货)
    通过一个demo了解Redux
    升级ChinaCock10.3.3激情版3注意事项
    解决uniDAC超时问题:已超过了锁请求超时时段。
    kbmMWSmartBind实现ListView绑定数据集进阶篇(一)
    通过输出日志到文件来检查app闪退原因
    VertScrollBox不能滑动
    使用kbmMW SmartBinding经验几则
  • 原文地址:https://www.cnblogs.com/ljzalc1022/p/8743443.html
Copyright © 2011-2022 走看看