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!
原文地址:https://www.cnblogs.com/--560/p/5183602.html