zoukankan      html  css  js  c++  java
  • 货车运输(LCA+最大生成树)

    神奇传送门

    恩,这是一道神奇的LCA+难度的题目。

    题目是这样的: 

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

    一开始看了看,以为是费用流(PS:一看就是费用流裸题嘛。。)

    然后发现有Q个询问。。

    完美TLE

    然后zxyer狠狠D了我一顿(%%%)这才发现写LCA是正解。。(太像了woc)

    好吧,说正解。

    这道题出现了Q个询问,我们很快就会想到RMQ和LCA

    可是这道题是个图,不一定是树。

    根据最大生成树的性质(载重量最大的那条路径一定在最大生成树上)

    RMQ处理区间最小值,而LCA有个性质,就是它一定在U到V的最短路上,而且是2个点到根节点的路径的第一个交点。所以到了LCA就没必要往上走了,

    因为路径是公共的,结果不会比LCA更优;

    然后RMQ处理最小值,再找一下LCA,输出载重量最小值

    然后就AC啦

    原来程序有BUG(好吧。终于DEBUG出来了。。)

    注意!写CMP函数时,如果用>=号会爆栈!

    下面贴程序~

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int n,m,num=0,q;
    struct edge{
        int next,to,value;
    }g[100010];
    int f[10010];
    int depth[10010];
    int visit[10010];
    int fa[10010][20];
    int r[50010];
    int u[50010],v[50010],w[50010];
    int dist [10010][20];
    int head[10010];
    int cmp(const int a,const int b) {
    return w[a]>w[b];}
    int getf(int x){
    return x==f[x]?x:f[x]=getf(f[x]);}
    void addedge(int u,int v,int value){
        g[++num].next=head[u];
        head[u]=num;
        g[num].to=v;
        g[num].value=value;
    }
    void kruskal(){
        for(int i=1;i<=n;i++) f[i]=i;
        for(int i=1;i<=m;i++) r[i]=i;    
        sort(r+1,r+m+1,cmp);
        for(int i=1;i<=m;i++)
        {
        int x=u[r[i]];
        int y=v[r[i]];
        x=getf(x);y=getf(y);
        if(x!=y){
        addedge(x,y,w[r[i]]);
        addedge(y,x,w[r[i]]);
        f[x]=y;
        }
        }
    }
    void prelca(int x){
        visit[x]=1;
        for(int i=1;(1<<i)<=depth[x];i++)
        {
            int c=fa[x][i-1];
            fa[x][i]=fa[c][i-1];
            dist[x][i]=min(dist[x][i-1],dist[c][i-1]);    
        }
        for(int i=head[x];i;i=g[i].next)
        {
            int v=g[i].to;
            if(!visit[v])
            {
                depth[v]=depth[x]+1;
                fa[v][0]=x;
                dist[v][0]=g[i].value;
                prelca(v);
            }    
        }
    }
    int lca(int x,int y)
    {
        int rr=2147483647;
        if(depth[x]<depth[y])swap(x,y);
        int dc=depth[x]-depth[y];
        for(int i=0;(1<<i)<=dc;i++)
        if(((1<<i)&dc)&&fa[x][i])
        {
            rr=min(rr,dist[x][i]);
            x=fa[x][i];    
    
        }    
        if(x==y)return rr;
        for(int i=15;i>=0;i--)
        if(fa[x][i]!=fa[y][i]&&depth[x]>=(1<<i)&&fa[x][i])
        {
            rr=min(rr,min(dist[x][i],dist[y][i]));    
            x=fa[x][i];
            y=fa[y][i];
        }
        return min(rr,min(dist[x][0],dist[y][0])); 
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        scanf("%d%d%d",&u[i],&v[i],&w[i]);
        kruskal();
        for(int i=1;i<=n;i++)
        if(!visit[i])prelca(i);
        scanf("%d",&q);
        for(int i=1;i<=q;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            if(getf(a)!=getf(b))printf("-1
    ");
            else printf("%d
    ",lca(a,b));
        }
        return 0;
    }

    注意:RMQ别打超限,调用空指针会WA的

  • 相关阅读:
    网络流24题-运输问题
    ASP.NET API
    面向对象理解
    冒泡排序
    HTTP Header 缓存
    HTTP Header
    Flask学习笔记07之模板渲染
    Flask学习笔记06之@before_request请求之前执行
    Flask报错:AssertionError: View function mapping is overwriting an existing endpoint function: inner
    装饰器03之多个装饰器的执行顺序
  • 原文地址:https://www.cnblogs.com/ghostfly233/p/6839461.html
Copyright © 2011-2022 走看看