zoukankan      html  css  js  c++  java
  • bnuoj 51275 并查集按深度合并建树

    道路修建 Large

    Time Limit: 5000ms
    Memory Limit: 131072KB
    64-bit integer IO format: %lld      Java class name: Main
    Type: 
    None
     
     

    无向图G初始有n个点,从1n依次标号,但是没有边,

    接下来有m次操作,从1m依次标号,你需要对每种操作输出相应的结果,操作分为两种:

    输入格式

    操作说明

    输出结果

    0_u_v

    加入一条连接标号为u和标号为v的点的边。

    输出加边后图G中连通块的个数。

    1_u_v

    查询标号为u和标号为v的点之间是否连通。

    如果连通,输出k,表示最早在第k次操作后标号为u和标号为v的点之间连通,否则输出0

    (输入格式中的下划线‘_’表示实际输入文件中的空格)

     

    Input

    第一行是一个正整数T(T leq 5),表示测试数据的组数,

    对于每组测试数据,

    第一行包含两个整数n(1 leq n leq 100000)m(0 leq m leq 500000)

    接下来m行,每行是3个整数puv,请注意所给的uv均是经过加密的,

    解密方式是u=u  xor  lastansv=v  xor  lastans ,其中lastans表示上一次操作的输出结果,

    初始lastans=0,保证p in {0,1},解密后1 leq u,v leq nu 
e v

     

    Output

    对于每组测试数据,

    输出m行,每行包含一个整数,表示操作的输出结果。

     

    Sample Input

    1
    4 7
    0 1 2
    1 1 0
    0 1 3
    0 0 1
    1 0 1
    0 1 7
    1 0 5

    Sample Output

    3
    0
    2
    2
    3
    1
    6

    Source

    #include<bits/stdc++.h>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    
    using namespace std;
    
    typedef long long ll;
    const int maxn=1000100;
    const int INF=1e9+10;
    
    int n,m;
    int fa[maxn],val[maxn];
    int rk[maxn];
    int op,u,v;
    int vis[maxn];
    
    int find(int x)
    {
        return fa[x]==x?x:find(fa[x]);
    }
    
    int main()
    {
        freopen("in.txt","r",stdin);
        int T;cin>>T;
        while(T--){
            scanf("%d%d",&n,&m);
            REP(i,1,n) fa[i]=i,val[i]=0;
            REP(i,1,n) rk[i]=1;
            REP(i,1,n) vis[i]=0;
            int lans=0,cnt=n;
            REP(i,1,m){
                scanf("%d%d%d",&op,&u,&v);
                u^=lans;v^=lans;
                int x=find(u),y=find(v);
                if(op==0){
                    if(x!=y){
                        if(rk[x]>rk[y]) swap(x,y);
                        fa[x]=y;
                        rk[y]=max(rk[y],rk[x]+1);
                        val[x]=i;
                        cnt--;
                    }
                    lans=cnt;
                }
                else{
                    if(x!=y) lans=0;
                    else{
                        int t=u;
                        vis[x]=i;
                        while(fa[t]!=t) vis[t]=i,t=fa[t];
                        int lca=x;
                        t=v;
                        while(fa[t]!=t){
                            if(vis[t]==i){
                                lca=t;break;
                            }
                            t=fa[t];
                        }
                        lans=0;
                        while(u!=lca) lans=max(lans,val[u]),u=fa[u];
                        while(v!=lca) lans=max(lans,val[v]),v=fa[v];
                    }
                }
                printf("%d
    ",lans);
            }
        }
        return 0;
    }
    View Code
    没有AC不了的题,只有不努力的ACMER!
  • 相关阅读:
    关于接口和接口中多肽问题的实例
    java 简单的单例 实现
    关于动态数组的问题
    一百以内的杨辉三角
    将阿拉伯数字转为中文大写读法
    sql server 2005 优化方法
    Sql Server 2005 数据库 优秀辅助工具推荐
    SSIS高级内容 系列一
    锁定
    SQL Server 2005查询处理结构用户模式计划(UMS)
  • 原文地址:https://www.cnblogs.com/--560/p/5183602.html
Copyright © 2011-2022 走看看