Description
有 (n) 个点,(m) 个操作,每次连接两个点,或者询问某两个点最早是在什么时刻开始连通的
Solution
考虑按秩合并并查集
对于每个结点,记录它到它父亲的边的权值为时间戳
询问时,类似朴素 LCA 暴力往上跳即可
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1000005;
int n,m,t1,t2,t3,fa[N],siz[N],w[N],dep[N],lastans;
void init()
{
for(int i=0;i<=n;i++) fa[i]=i, siz[i]=1;
}
int find(int x)
{
while(x!=fa[x]) x=fa[x];
return x;
}
void merge(int p,int q,int val)
{
p=find(p);
q=find(q);
if(p==q) return;
if(siz[p]<siz[q]) swap(p,q);
fa[q]=p;
w[q]=val;
siz[p]+=siz[q];
}
int calcdep(int p)
{
if(fa[p]==p) return dep[p]=1;
return dep[p]=calcdep(fa[p])+1;
}
int getans(int p,int q)
{
int ans=0;
calcdep(p);
calcdep(q);
if(dep[p]<dep[q]) swap(p,q);
while(dep[p]>dep[q])
{
ans=max(ans,w[p]);
p=fa[p];
}
while(p!=q)
{
ans=max(ans,w[p]);
ans=max(ans,w[q]);
p=fa[p];
q=fa[q];
}
return ans;
}
signed main()
{
ios::sync_with_stdio(false);
cin>>n>>m;
init();
int ind=0;
for(int i=1;i<=m;i++)
{
cin>>t1>>t2>>t3;
t2^=lastans;
t3^=lastans;
if(t1)
{
if(find(t2)==find(t3))
{
cout<<(lastans=getans(t2,t3))<<endl;
}
else
{
cout<<0<<endl;
lastans=0;
}
}
else
{
merge(t2,t3,++ind);
}
}
}