zoukankan      html  css  js  c++  java
  • noip提高组2013 货车运输(luogu 1967)

    原题链接:https://www.luogu.org/problem/show?pid=1967

    对于这个题,需要用到一些最小生成树的一些性质。

    对于一个图的任意两棵最小生成树,每条边的权值都是一一对应的。

    对于一个图的所有生成树,任意两点之间的路径(每棵树上唯一确定),最小生成树上,最长的边最短。

    最大生成树反之亦然。任意两点之间,最短的边最长。

    此题为双向图,在边权问题上,与无向图没什么区别。。。

    于是对于每一组询问的两个节点,求出他们的LCA,保存两个点分别走到LCA时的边权最小的权值。

    如果两个点不在同一棵树内,当然不会有LCA。

    然后就是LCA板子啥的了,蒟蒻码力太弱,写了好长。。。

    #include<cstdio>
    #include<cstring> 
    #include<algorithm>
    using namespace std;
    void read(int &y)//快速读入 
    {
        y=0;char x=getchar();
        while(x<'0'||x>'9') x=getchar();
        while(x>='0'&&x<='9')
        {
            y=y*10+x-'0';
            x=getchar();
        }
    }
    struct edge
    {
        int u,v,w;
    }e[50005];
    bool cmp(edge x,edge y)//最大生成树边权可从大到小排序 
    {
        return x.w>y.w;
    } 
    int n,m,q,cnt;
    int head[20005],nxt[20005],to[20005],d[20005],f[10005],dep[10005];
    int fa[10005][25],minv[10005][25];
    void add(int u,int v,int w)//邻接表存边 
    {
        to[cnt]=v;
        d[cnt]=w;
        nxt[cnt]=head[u];
        head[u]=cnt++;
    }
    int find(int x)//并查集 
    {
        if(x==f[x]) return x;
        return f[x]=find(f[x]);
    }
    void dfs(int x,int y)//dfs找出每个点的深度 
    {
        for(int i=head[x];i!=-1;i=nxt[i])
        {
            if(i!=y)
            {
                dep[to[i]]=dep[x]+1;
                fa[to[i]][0]=x;
                minv[to[i]][0]=d[i];
                dfs(to[i],i^1);
            }
        }
    }
    int lca(int x,int y)//LCA
    {
        if(dep[x]>dep[y])
        {
            int t=x;
            x=y;
            y=t;
        }
        int ans=(1<<30);
        for(int i=15;i>=0;i--)
        {
            if(dep[fa[y][i]]>=dep[x])
            {
                ans=min(ans,minv[y][i]);
                y=fa[y][i];
            }
        }
        if(x==y) return ans;
        for(int i=15;i>=0;i--)
        {
            if(fa[x][i]!=fa[y][i])
            {  
                ans=min(ans,min(minv[x][i],minv[y][i]));  
                x=fa[x][i];  
                y=fa[y][i];  
            }
        }
        return fa[x][0]==0 ? -1 : min(ans,min(minv[x][0],minv[y][0]));
    }
    int main()
    {
        read(n);read(m);
        int u,v,w;
        for(int i=0;i<m;i++)
        {
            read(e[i].u);read(e[i].v);read(e[i].w);
        }
        memset(head,-1,sizeof(head));
        sort(e,e+m,cmp);
        for(int i=1;i<=n;i++) f[i]=i;
        for(int i=0;i<m;i++)
        {
            if(find(e[i].u)!=find(e[i].v))
            {
                add(e[i].u,e[i].v,e[i].w);
                add(e[i].v,e[i].u,e[i].w);
                f[find(e[i].u)]=find(e[i].v);
            }
        }
        dep[1]=1;dfs(1,-1);
        for(int j=1;j<=15;j++)
        {
            for(int i=1;i<=n;i++)
            {
                fa[i][j]=fa[fa[i][j-1]][j-1];
                minv[i][j]=min(minv[i][j-1],minv[fa[i][j-1]][j-1]);
            }
        }
        int q,x,y;read(q);
        for(register int i=0;i<q;i++)
        {
            read(x);read(y);
            printf("%d
    ",lca(x,y));
        }
        return 0;
    }
  • 相关阅读:
    SQL Server 2019 安装错误
    SQL Server Cardinality Estimation 简介
    SQL Server 要避免的编程坏习惯
    SQL Server 中SET XACT_ABORT设置的作用
    SQL Server nested transaction try...catch 处理模板
    SVN迁移至gitlab
    安装单机版RabbitMQ
    校验MySQL主从数据并修复
    使用Xtrabackup对数据库进行部分备份恢复
    MySQL之Xtrabackup备份还原与binlog恢复
  • 原文地址:https://www.cnblogs.com/zeroform/p/7545238.html
Copyright © 2011-2022 走看看