BZOJ4998星球联盟 LCT+并查集
Posted CQzhangyu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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
1 2
4 3
4 5
2 3
1 3
4 5
2 4
Sample Output
No
3
2
5
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\n"); else printf("%d\n",sum); } return 0; }//5 3 4 1 2 4 3 4 5 2 3 1 3 4 5 2 4
以上是关于BZOJ4998星球联盟 LCT+并查集的主要内容,如果未能解决你的问题,请参考以下文章