zoukankan      html  css  js  c++  java
  • 【BZOJ4998】星球联盟 LCT+并查集

    【BZOJ4998】星球联盟

    Description

    在遥远的S星系中一共有N个星球,编号为1…N。其中的一些星球决定组成联盟,以方便相互间的交流。但是,组成联盟的首要条件就是交通条件。初始时,在这N个星球间有M条太空隧道。每条太空隧道连接两个星球,使得它们能够相互到达。若两个星球属于同一个联盟,则必须存在一条环形线路经过这两个星球,即两个星球间存在两条没有公共隧道的路径。为了壮大联盟的队伍,这些星球将建设P条新的太空隧道。这P条新隧道将按顺序依次建成。一条新轨道建成后,可能会使一些星球属于同一个联盟。你的任务是计算出,在一条新隧道建设完毕后,判断这条新轨道连接的两个星球是否属于同一个联盟,如果属于同一个联盟就计算出这个联盟中有多少个星球。

    Input

    第1行三个整数N,M和P,分别表示总星球数,初始时太空隧道的数目和即将建设的轨道数目。
    第2至第M+1行,每行两个整数,表示初始时的每条太空隧道连接的两个星球编号。
    第M+2行至第M+P+1行,每行两个整数,表示新建的太空隧道连接的两个星球编号。
    这些太空隧道按照输入的顺序依次建成。
    1≤N,M,P≤200000

    Output

    输出共P行。
    如果这条新的太空隧道连接的两个星球属于同一个联盟,就输出一个整数,表示这两个星球所在联盟的星球数。
    如果这条新的太空隧道连接的两个星球不属于同一个联盟,就输出"No"(不含引号)。

    Sample Input

    5 3 4
    1 2
    4 3
    4 5
    2 3
    1 3
    4 5
    2 4

    Sample Output

    No
    3
    2
    5

    HINT

    题解:做完长跑那题后这题就水了。

    用并查集判环,如果出现环,就在LCT上将这些点缩成一个点即可。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    const int maxn=200010;
    int n,m,p;
    int f[maxn],siz[maxn],F[maxn];
    int sum;
    struct node
    {
    	int ch[2],fa,rev;
    }s[maxn];
    int Find(int x)
    {
    	return (F[x]==x)?x:(F[x]=Find(F[x]));
    }
    int find(int x)
    {
    	return (f[x]==x)?x:(f[x]=find(f[x]));
    }
    bool isr(int x)	{return s[find(s[x].fa)].ch[0]!=x&&s[find(s[x].fa)].ch[1]!=x;}
    void pushdown(int x)
    {
    	if(s[x].rev)
    	{
    		swap(s[x].ch[0],s[x].ch[1]);
    		if(s[x].ch[0])	s[s[x].ch[0]].rev^=1;
    		if(s[x].ch[1])	s[s[x].ch[1]].rev^=1;
    		s[x].rev=0;
    	}
    }
    void updata(int x)
    {
    	if(!isr(x))	updata(find(s[x].fa));
    	pushdown(x);
    }
    void rotate(int x)
    {
    	int y=find(s[x].fa),z=find(s[y].fa),d=(x==s[y].ch[1]);
    	if(!isr(y))	s[z].ch[y==s[z].ch[1]]=x;
    	s[y].fa=x,s[x].fa=z,s[y].ch[d]=s[x].ch[d^1];
    	if(s[x].ch[d^1])	s[s[x].ch[d^1]].fa=y;
    	s[x].ch[d^1]=y;
    }
    void splay(int x)
    {
    	updata(x);
    	while(!isr(x))
    	{
    		int y=find(s[x].fa),z=find(s[y].fa);
    		if(!isr(y))
    		{
    			if((x==s[y].ch[0])^(y==s[z].ch[0]))	rotate(x);
    			else	rotate(y);
    		}
    		rotate(x);
    	}
    }
    void access(int x)
    {
    	for(int y=0;x;splay(x),s[x].ch[1]=y,s[y].fa=x,y=x,x=find(s[x].fa));
    }
    void maker(int x)
    {
    	access(x),splay(x),s[x].rev^=1;
    }
    void link(int x,int y)
    {
    	maker(x),s[x].fa=y;
    }
    void dfs(int x,int y)
    {
    	if(!x)	return ;
    	sum+=siz[x];
    	if(x!=y)	siz[y]+=siz[x],f[x]=y;
    	dfs(s[x].ch[0],y),dfs(s[x].ch[1],y);
    }
    inline int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=getchar();
    	return ret*f;
    }
    void add(int a,int b)
    {
    	sum=0;
    	if(Find(a)!=Find(b))
    	{
    		F[F[a]]=F[b];
    		link(a,b);
    	}
    	else
    	{
    		maker(a),access(b),splay(b),dfs(b,b),s[b].ch[0]=s[b].ch[1]=0;
    	}
    }
    int main()
    {
    	n=rd(),m=rd(),p=rd();
    	int i,a,b;
    	for(i=1;i<=n;i++)	F[i]=f[i]=i,siz[i]=1;
    	for(i=1;i<=m;i++)	a=find(rd()),b=find(rd()),add(a,b);
    	for(i=1;i<=p;i++)
    	{
    		a=find(rd()),b=find(rd()),add(a,b);
    		if(!sum)	printf("No
    ");
    		else	printf("%d
    ",sum);
    	}
    	return 0;
    }//5 3 4 1 2 4 3 4 5 2 3 1 3 4 5 2 4
  • 相关阅读:
    C#性能优化实践
    JavaScript类型转换
    JSON基础
    EasyUI DataGrid 内部input的事件
    WPF之Binding基础二 控件作为Binding的数据源
    WPF之Binding基础一 UI Binding Source
    JavaScript里面的“类”
    SqlServer随笔
    对象和类型
    浅谈类
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7398844.html
Copyright © 2011-2022 走看看