zoukankan      html  css  js  c++  java
  • 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
    ",lastans);
            }
        }
        return 0;
    } 
  • 相关阅读:
    Oracle连接数一直在增
    ora00020: maximum number of processes (150) exeeded
    oracle归档日志满了
    C# ZPL
    error CS0227: 不安全代码只会在使用 /unsafe 编译的情况下出现
    最全zpl语言指令解析(含乱码)
    ZPL 打印机实例
    ora-01400 无法将NULL插入 ID 解决方法
    windows 选择时间控件(选择日期, 小时分钟秒)
    用户登陆检验----没有优化,大神可以帮忙优化优化
  • 原文地址:https://www.cnblogs.com/zhangleo/p/11059418.html
Copyright © 2011-2022 走看看