zoukankan      html  css  js  c++  java
  • bzoj4998 星球联盟

    bzoj4998 星球联盟


    原题链接


    题解

    先按照输入顺序建一棵树(森林),然后用一个并查集维护联盟的关系,对于不是树上的边(a-b),就把(a-lca(a,b),b-lca(a,b))全部合并(一个圈),输出(a)所在并查集的(Siz),树边输出(No)


    Code

    
    // It is made by XZZ
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #define Fname "CJOJ2550"
    using namespace std;
    #define rep(a,b,c) for(rg int a=b;a<=c;a++)
    #define drep(a,b,c) for(rg int a=b;a>=c;a--)
    #define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
    #define il inline
    #define rg register
    #define vd void
    typedef long long ll;
    il int gi(){
        rg int x=0;rg char ch=getchar();
        while(ch<'0'||ch>'9')ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x;
    }
    const int maxn=200100,maxm=200100<<2;
    int id,fir[maxn],nxt[maxm],dis[maxm];
    int fa[maxn],Fa[maxn],FA[maxn],dep[maxn],Siz[maxn];
    int A[maxn<<1],B[maxn<<1];
    bool yes[maxn<<1];
    il int hd(int s){return fa[s]==s?s:(fa[s]=hd(fa[s]));}
    il int Hd(int s){return Fa[s]==s?s:(Fa[s]=Hd(Fa[s]));}
    il vd add(int a,int b){nxt[++id]=fir[a],fir[a]=id,dis[id]=b;}
    il vd dfs(int now){erep(i,now)if(!dep[dis[i]])dep[dis[i]]=dep[now]+1,FA[dis[i]]=now,dfs(dis[i]);}
    il vd doit(int s){
        rg int a=Hd(s),b=Hd(FA[s]);
        if(a^b)Siz[b]+=Siz[a],Fa[a]=b;
    }
    int main(){
        // freopen(Fname".in","r",stdin);
        // freopen(Fname".out","w",stdout);
        int a,b,n=gi(),m=gi(),p=gi();
        rep(i,1,n)fa[i]=Fa[i]=i,Siz[i]=1;
        rep(i,1,m+p){
    	a=A[i]=gi(),b=B[i]=gi();
    	if(hd(a)^hd(b))add(a,b),add(b,a),fa[hd(a)]=hd(b);
    	else yes[i]=1;
        }
        rep(i,1,n)if(!FA[i])FA[i]=-1,dep[i]=1,dfs(i);
        rep(i,1,m)if(yes[i]){
    	a=A[i],b=B[i];
    	while(a^b)
    	    if(dep[a]>dep[b])doit(a),a=FA[a];
    	    else doit(b),b=FA[b];
        }
        rep(i,1,p)if(yes[i+m]){
    	a=A[i+m],b=B[i+m];
    	while(a^b)
    	    if(dep[a]>dep[b])doit(a),a=FA[a];
    	    else doit(b),b=FA[b];
    	printf("%d
    ",Siz[Hd(a)]);
        }else puts("No");
        return 0;
    }
    
    博主是蒟蒻,有问题请指出,谢谢!
    本博客中博文均为原创,未经博主允许请勿随意转载,谢谢。
  • 相关阅读:
    函数PARSENAME使用和截取字符串
    转换为标准IPv4格式
    字母转为大写字母
    字母转为小写字母
    删除多个重复记录
    大写字母或小写字母转换为数字
    给不合法的格式转换成标准格式(案例)
    SQL SERVER动态列名
    快速生成基数的辅助表
    动态为表添加字段
  • 原文地址:https://www.cnblogs.com/xzz_233/p/7472669.html
Copyright © 2011-2022 走看看