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

    倍增求LCA+最大生成树

    题目给出的是一张图,在图上有很多算法无法实现,所以要将其转化为树

    题中可以发现货车的最后的载重量是由权值最小的一条边决定的,所以我们求最大生成树

    求完最大生成树后我们得到一个森林

    现在转化为了求两点路径经过边的边权的最小值,用倍增算法进行计算

    #include <bits/stdc++.h>
    #define inf 1e9
    using namespace std;
    const int MAXN=10100;
    int n,m,first[MAXN],nxt[MAXN*10],point[MAXN*10],len[MAXN*10];
    int q,tot,fa[MAXN],f[MAXN][21],chmin[MAXN][21],vi[MAXN],de[MAXN];
    struct node
    {
        int u,v,len;
    }sh[MAXN*5];
    void add_edge(int x,int y,int z)
    {
        tot++;
        nxt[tot]=first[x];
        first[x]=tot;
        point[tot]=y;
        len[tot]=z;
    }
    void dfs(int x,int father,int deep,int last,int visit)
    {
        de[x]=deep;
        vi[x]=visit;
        f[x][0]=father;//倍增father数组
        chmin[x][0]=last;//记录上一条边的权值
        for (int i=first[x];i!=-1;i=nxt[i])
        {
            if (point[i]!=father)
            {
                dfs(point[i],x,deep+1,len[i],visit);
            }
        }
    }
    int getfather(int x)
    {
        if (fa[x]==x)
          return fa[x];
        fa[x]=getfather(fa[x]);
        return fa[x];
    }
    bool cmp(node a,node b)
    {
        return a.len>b.len;
    }
    int lca(int a,int b)//倍增求LCA
    {
        if (getfather(a)!=getfather(b))
          return -1;
        if (de[a]>de[b])
          swap(a,b);
        int MIN=inf;
        for (int i=20;i>=0;i--)
        {
            if (de[f[b][i]]>=de[a])
            {
                MIN=min(MIN,chmin[b][i]);
                b=f[b][i];
            }
        }
        if (a==b)
          return MIN;
        for (int i=20;i>=0;i--)
        {
            if (f[a][i]!=f[b][i])
            {
                MIN=min(MIN,min(chmin[a][i],chmin[b][i]));
                a=f[a][i];
                b=f[b][i];
            }
        }
        MIN=min(MIN,min(chmin[a][0],chmin[b][0]));
        return MIN;
    }
    int main()
    {
        tot=-1;
        memset(nxt,-1,sizeof(nxt));
        memset(first,-1,sizeof(first));
        scanf("%d%d",&n,&m);
        for (int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&sh[i].u,&sh[i].v,&sh[i].len);
        }
        for (int i=1;i<=n;i++)
          fa[i]=i;
        sort(sh+1,sh+1+m,cmp);
        for (int i=1;i<=m;i++)
        {
            if (getfather(sh[i].u)!=getfather(sh[i].v))
            {
                fa[getfather(sh[i].u)]=getfather(sh[i].v);
                add_edge(sh[i].u,sh[i].v,sh[i].len);
                add_edge(sh[i].v,sh[i].u,sh[i].len);
            }
        }//求最大生成树
        int now=0;
        for (int i=1;i<=n;i++)//可能有多棵树,每棵树分别考虑
        {
            if (vi[i]!=0)
              continue;
            now++;
            dfs(i,0,0,inf,now);
            f[i][0]=i;
            chmin[i][0]=inf;
        }
        for (int j=1;j<=20;j++)
        {
            for (int i=1;i<=n;i++)
            {
                f[i][j]=f[f[i][j-1]][j-1];
                chmin[i][j]=min(chmin[i][j-1],chmin[f[i][j-1]][j-1]);//进行倍增
            }
        }
        scanf("%d",&q);
        for (int i=1;i<=q;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            printf("%d
    ",lca(x,y));
        }
    }

    倍增求LCA时避免父亲倍增数组出现0,倍增记录最小值时,简单写法

        int now=0;
        for (int i=1;i<=n;i++)
        {
            if (vi[i]!=0)
              continue;
            now++;
            dfs(i,0,0,inf,now);
            f[i][0]=i;//使当前的father==i
            chmin[i][0]=inf;//记录的最小值
        }

    求deep时,注意不是求距离上的deep,而是层数

    void dfs(int x,int father,int deep,int last,int visit)
    {
        de[x]=deep;
        vi[x]=visit;
        f[x][0]=father;
        chmin[x][0]=last;
        for (int i=first[x];i!=-1;i=nxt[i])
        {
            if (point[i]!=father)
            {
                dfs(point[i],x,deep+1,len[i],visit);//deep是+1,不是加len[i],注意
            }
        }
    }
  • 相关阅读:
    select、poll和epoll
    Linux 常用命令之文件和目录
    SmartPlant Review 帮助文档机翻做培训手册
    SmartPlant Foundation 基础教程 3.4 菜单栏
    SmartPlant Foundation 基础教程 3.3 标题栏
    SmartPlant Foundation 基础教程 3.2 界面布局
    SmartPlant Foundation 基础教程 3.1 DTC登陆界面
    SmartPlant Foundation 基础教程 1.4 SPF架构
    SmartPlant Foundation 基础教程 1.3 SPF其他功能
    SmartPlant Foundation 基础教程 1.2 SPF集成设计功能
  • 原文地址:https://www.cnblogs.com/huangchenyan/p/11128841.html
Copyright © 2011-2022 走看看