bzoj 4668

首先显然是并查集了

每次连边就是合并两个集合,最后会形成很多连通块,是个森林的结构

考虑在连边的时候加入一个权值表示这条边是第几次被加入图中的,那么每次查询的答案即为$x$到$y$路径上权值最大值

由于并查集按秩合并的复杂度是$O(log_{2}n)$,因此合并时直接按秩合并,查询时暴力向上跳即可

复杂度$O(nlog_{2}n)$

代码:

#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
int f[500005];
int pre[500005];
int siz[500005];
bool vis[500005];
int n,m,lastans;
int ans=0;
inline int findf(int x)
{
    while(x!=f[x])x=f[x];
    return x;
}
inline int query_find(int x)
{
    vis[x]=1;
    while(x!=f[x])
    {
        x=f[x];
        vis[x]=1;
    }
    return x;
}
inline int query_check(int x)
{
    while(x!=f[x]&&!vis[x])
    {
        ans=max(ans,pre[x]);
        x=f[x];
    }
    return x;
}
inline int read()
{
    int f=1,x=0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int main()
{
//    freopen("coldwar.in","r",stdin);
//    freopen("coldwar.out","w",stdout);
    n=read(),m=read();
    for(register int i=1;i<=n;++i)siz[i]=1,f[i]=i;
    int lastans=0;
    int tot=0;
    for(register int i=1;i<=m;++i)
    {
        int typ=read(),x=read(),y=read();
        x^=lastans,y^=lastans;
        if(typ==0)
        {
            int f1=findf(x),f2=findf(y);
            if(f1==f2){tot++;continue;}
            if(siz[f1]<siz[f2])swap(f1,f2);
            f[f2]=f1,siz[f1]+=siz[f2],pre[f2]=++tot;
        }else
        {
            ans=0;
            int f1=query_find(x),f2=query_check(y);
            if(!vis[f2])
            {
                int tempx=x;
                while(tempx!=f1)vis[tempx]=0,tempx=f[tempx];
                vis[f1]=0;
                lastans=0;
            }else 
            {
                int tempx=x;
                bool flag=0;
                if(tempx==f2)flag=1;
                while(tempx!=f1)
                {
                    if(!flag)ans=max(ans,pre[tempx]);
                    vis[tempx]=0;
                    tempx=f[tempx];
                    if(tempx==f2)flag=1;
                }
                vis[f1]=0;
                lastans=ans;
            }
            printf("%d\n",lastans);
        }
    }
    return 0;
} 

 

posted @ 2019-06-20 16:14  lleozhang  Views(98)  Comments(0Edit  收藏  举报
levels of contents