bzoj 4668 冷战 —— 并查集按秩合并

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4668

按秩合并维护并查集的树结构,然后暴力找路径上的最大边权即可。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int const xn=5e5+5;
int n,m,fa[xn],t[xn],dep[xn],siz[xn],ans,cnt;
int rd()
{
    int ret=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();}
    while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
    return f?ret:-ret;
}
int find(int x)
{
    if(fa[x]==x)return x;
    int f=find(fa[x]);
    dep[x]=dep[fa[x]]+1;
    return f;
}
void merge(int x,int y,int tim)
{
    int u=find(x),v=find(y);
    if(u==v)return;
    if(siz[u]<siz[v])swap(u,v);
    fa[v]=u; siz[u]+=siz[v]; t[v]=tim;
}
int query(int x,int y)
{
    int u=find(x),v=find(y);
    if(u!=v)return 0;
    int ret=0;
    if(dep[x]<dep[y])swap(x,y);
    while(dep[x]>dep[y])ret=max(ret,t[x]),x=fa[x];
    while(x!=y)ret=max(ret,max(t[x],t[y])),x=fa[x],y=fa[y];
    return ret;
}
int main()
{
    n=rd(); m=rd();
    for(int i=1;i<=n;i++)fa[i]=i,siz[i]=1;
    for(int i=1,p,u,v;i<=m;i++)
    {
        p=rd(); u=rd(); v=rd();
        u^=ans; v^=ans;
        if(!p)merge(u,v,++cnt);
        else printf("%d\n",ans=query(u,v));
    }
    return 0;
}

 

posted @ 2018-10-06 22:50  Zinn  阅读(119)  评论(0编辑  收藏  举报