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;
    } 
  • 相关阅读:
    实验3 简单的分支与循环结构 2.利用循环计算n个圆柱体体积。
    实验 3 简单的分支与循环结构 第一题 编写求圆面积的程序,要求当输入的半径r<=0时,提示输入错误,要求r为浮点型,r的数值是动态的由键盘输入
    心得3
    作业 3 应用分支与循环结构解决问题
    实验5 函数
    实验1 题目2
    第三,四章学习心得
    第2章学习心得
    第一章学习心得
    5-3
  • 原文地址:https://www.cnblogs.com/zhangleo/p/11059418.html
Copyright © 2011-2022 走看看