zoukankan      html  css  js  c++  java
  • BNU 51275 道路修建 Large 并查集

    分析(引入Q神题解  %%%Q)

    如果使用可持久化并查集,二分答案判定连通性,复杂度是O(mlog3n),不能在时限内出解。
    考虑到并查集实际上是一棵树,可以尝试在边上维护一些信息,假设t时刻加了一条边(u,v),若u和v此时未连通,
    则在root(u)和root(v)之间连一条权值为t的边,表示u所在集合以及v所在集合在t时刻连通,
    这样对于一组查询(u,v),如果u和v位于同一个连通块内,只需找出并查集中u到v的路径上的权值最大值,
    很显然这样是不能路径压缩的,但是可以按秩合并保证树高是O(logn),总的复杂度是O(mlogn)。

    这样找到树根是logn,路径查询也是logn 总的是mlogn,关键是代码很好写

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    const int N=1e5+5;
    int fa[N],r[N],p[N],vis[N],n;
    void init()
    {
       for(int i=1;i<=n;++i)
       {
          fa[i]=i;
          p[i]=r[i]=0;
          vis[i]=-1;
       }
    }
    int find(int x)
    {
        if(x==fa[x])return x;
        return find(fa[x]);
    }
    bool Union(int u,int v,int t)
    {
        u=find(u);
        v=find(v);
        if(u==v)return false;
        if(r[u]>r[v])
        {
           fa[v]=u;
           p[v]=t;
        }
        else
        {
           fa[u]=v;
           p[u]=t;
           if(r[u]==r[v])++r[v];
        }
        return true;
    }
    int getans(int u,int v)
    {
        int now=0,x=u,ans;
        while(1)
        {
           vis[x]=now;
           if(x==fa[x])break;
           now=max(now,p[x]);
           x=fa[x];
        }
        x=v,now=0;
        while(1)
        {
           if(vis[x]!=-1)
           {
               now=max(now,vis[x]);
               ans=now;
               break;
           }
           now=max(now,p[x]);
           x=fa[x];
        }
        x=u;
        while(1)
        {
           vis[x]=-1;
           if(x==fa[x])break;
           x=fa[x];
        }
        return ans;
    }
    int main()
    {
        int T,la,m;
        scanf("%d",&T);
        while(T--)
        {
           scanf("%d%d",&n,&m);
           init(),la=0;
           int op,u,v,blk=n;
           for(int i=1;i<=m;++i)
           {
              scanf("%d%d%d",&op,&u,&v);
              u^=la,v^=la;
              if(op)
              {
                  int x=find(u);
                  int y=find(v);
                  if(x!=y)
                      la=0;
                  else la=getans(u,v);
                  printf("%d
    ",la);
              }
              else
              {
                  if(Union(u,v,i))blk--;
                  la=blk;
                  printf("%d
    ",la);
              }
           }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    java验证身份证号码
    java两种定时器
    Nginx负载均衡配置
    python中import list,dictionary常量在class实例化时遇到的坑
    UnicodeDecodeError: 'gbk' codec can't decode byte 0xaf in position 218: illegal multibyte sequence解决方案
    jenkins+gradle打包android遇到的坑
    mac安装神器brew
    mac配置jenkins遇到的问题及解决办法
    django框架搭建web服务
    贯众云平台脚本编写之判断、循环以及shell命令的使用
  • 原文地址:https://www.cnblogs.com/shuguangzw/p/5185482.html
Copyright © 2011-2022 走看看