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

    题目描述

    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

    分析:
    这道题说白了就是使两点之间所有路径中的最小路径权值最大
    首先我们考虑到,如果直接连通的两点之间都多条路径,我们肯定首选权值最大的那一条,
    因此我们可以把整个图简化一下,选中一些权值很大的边,
    把无用的边(也就是可以等效替换掉的)删掉,选尽量少的边
    这些边可以联通所有点,而且权值最大,
    这不就是最大生成树吗。。。
    于是我们把一幅图转化成了一棵树,
    现在的问题就是怎样求树上两点之间的路径中的最小值,
    秒想:树链剖分
    然而树链剖分又臭又长,常数还大
    所以我们选择一种更为优越的写法:树上倍增
    建立两个数组,一个记录该节点向上跳2^i步的爸爸
    一个记录该节点向上跳2^i步经过的路径的最小值
    这样在每次询问的时候进行一次类似LCA的查询就ok了

    (这道题的AC过程真的很尬,昨天就在写这道题,可能是因为一开始的思路不是很清楚,
    改动很多,交上去的时候一直mle和wa,在线下测试的时候数据通过了,
    但luogu就是不认啊,
    这里写图片描述
    昨天晚上把我逼疯之后,今天早上重构,结果就1A了!!! exm!!!)

    这里写代码片
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    
    using namespace std;
    
    const int N=10001;
    struct node{
        int x,y,v;
    };
    node wy[N*5];
    struct node1{
        int x,y,nxt,v;
    };
    node1 way[N<<1];
    int n,m,q,st[N],tot=0;
    int ba[N],mn[N][20],f[N][20],deep[N];
    int un,de=0;
    
    int cmp(const node &a,const node &b)
    {
        return a.v>b.v;
    }
    
    void add(int u,int w,int z)
    {
        tot++;
        way[tot].x=u;way[tot].y=w;way[tot].v=z;way[tot].nxt=st[u];st[u]=tot;
        tot++;
        way[tot].x=w;way[tot].y=u;way[tot].v=z;way[tot].nxt=st[w];st[w]=tot;
    }   
    
    void unionn(int r1,int r2)
    {
        ba[r1]=r2;
    }   
    
    int find(int a)
    {
        if (ba[a]!=a) ba[a]=find(ba[a]);
        return ba[a];
    }
    
    void doit()
    {
        int i,j;
        for (i=1;i<=n;i++) ba[i]=i;
        for (i=1;i<=m;i++)
        {
            int r1=find(wy[i].x);
            int r2=find(wy[i].y);
            if (r1!=r2)
            {
                unionn(r1,r2);
                add(wy[i].x,wy[i].y,wy[i].v);
            }
        }
    }
    
    void dfs(int now,int dep,int faa)
    {
        deep[now]=dep;
        f[now][0]=faa;
        de=max(de,dep);
        for (int i=st[now];i;i=way[i].nxt)
            if (way[i].y!=faa)
            {
                mn[way[i].y][0]=way[i].v;
                dfs(way[i].y,dep+1,now);
            }
    }
    
    void cl()
    {
        int i,j;
        for (i=1;i<=un;i++)
            for (j=1;j<=n;j++)
            {
                f[j][i]=f[f[j][i-1]][i-1];
                mn[j][i]=min(mn[j][i-1],mn[f[j][i-1]][i-1]);
            }
    }
    
    int ask(int u,int w)
    {
        int i,ans=100001;
        if (deep[u]<deep[w]) 
            swap(u,w);
        int d=deep[u]-deep[w];
        if (d)
           for (i=0;i<=un&&d;i++,d>>=1)
               if (d&1)
               {
                    ans=min(ans,mn[u][i]);
                    u=f[u][i];
               }
        if (u==w) return ans;
        for (i=un;i>=0;i--)
            if (f[u][i]!=f[w][i])
            {
                ans=min(ans,mn[u][i]);
                ans=min(ans,mn[w][i]);
                u=f[u][i];
                w=f[w][i];
            }
        ans=min(ans,mn[u][0]);
        ans=min(ans,mn[w][0]);
        return ans;
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for (int i=1;i<=m;i++)
            scanf("%d%d%d",&wy[i].x,&wy[i].y,&wy[i].v);
        sort(wy+1,wy+1+m,cmp);
        doit();
        for (int i=1;i<=n;i++)
            if (deep[i]==0)
               dfs(1,1,0);
        un=(int)log(de)/log(2)+1;
        cl();
        scanf("%d",&q);
        for (int i=1;i<=q;i++)
        {
            int u,w;
            scanf("%d%d",&u,&w);
            if (find(u)!=find(w))
                printf("-1
    ");
            else printf("%d
    ",ask(u,w));
        }
        return 0;
    }
  • 相关阅读:
    @WebFilter注解
    Value '0000-00-00' can not be represented as java.sql.Date解决办法
    项目配置 xml文件时 报错提示(The reference to entity "useSSL" must end with the ';' delimiter.)
    eclipse中取消自动生成的TODO Auto-generated method stub
    eclipse中把选中的代码全部变成大写或者小写的快捷键
    在浏览器访问Tomcat的时候报错java.lang.IllegalArgumentException: Control character in cookie value or attribute.
    Tomcat报错,内存溢出的错误Exception in thread "http-bio-8080-exec-13" java.lang.OutOfMemoryError: PermGen space
    java.io.Serializable的作用
    idea快捷键总结
    MYSQL分页limit速度太慢优化方法
  • 原文地址:https://www.cnblogs.com/wutongtong3117/p/7673544.html
Copyright © 2011-2022 走看看