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维护森林
每次加进来的边要不就是树边要不就是非树边
树边直接加上,并查集维护连通性直接LCT太慢啦啦啦
非树边就会成环,设这条边是(x,y)
把x~y的路径提取出来,就是这个环
再用一个并查集维护点属于的边双编号
暴力dfs维护并查集
别人的LCT模板怎么这么好看啊
不管了以后我的模板就是这个
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
int fa1[210000],fa2[210000],siz[210000];
int findfa1(int x){return fa1[x]==x?fa1[x]:fa1[x]=findfa1(fa1[x]);}
int findfa2(int x){return fa2[x]==x?fa2[x]:fa2[x]=findfa2(fa2[x]);}
struct lct
{
int son[2],f;
int fz;
}tr[210000];
bool isroot(int x){return tr[findfa1(tr[x].f)].son[0]!=x&&tr[findfa1(tr[x].f)].son[1]!=x;}
void pushdown(int x)
{
if(tr[x].fz)
{
swap(tr[x].son[0],tr[x].son[1]);
if(tr[x].son[0])tr[tr[x].son[0]].fz^=1;
if(tr[x].son[1])tr[tr[x].son[1]].fz^=1;
tr[x].fz=0;
}
}
void update(int x)
{
if(!isroot(x))update(findfa1(tr[x].f));
pushdown(x);
}
void rotate(int x)
{
int y=findfa1(tr[x].f),z=findfa1(tr[y].f),d=(x==tr[y].son[1]);
if(!isroot(y))tr[z].son[y==tr[z].son[1]]=x;
tr[y].f=x;tr[x].f=z;tr[y].son[d]=tr[x].son[d^1];
if(tr[x].son[d^1])tr[tr[x].son[d^1]].f=y;
tr[x].son[d^1]=y;
}
void splay(int x)
{
update(x);
while(!isroot(x))
{
int y=findfa1(tr[x].f),z=findfa1(tr[y].f);
if(!isroot(y))
{
if((x==tr[y].son[0])^(y==tr[z].son[0]))rotate(x);
else rotate(y);
}
rotate(x);
}
}
void access(int x)
{
int y=0;
while(x!=0)
{
splay(x);
tr[x].son[1]=y;
if(y)tr[y].f=x;
y=x;x=findfa1(tr[x].f);
}
}
void markroot(int x){access(x);splay(x);tr[x].fz^=1;}
void link(int x,int y){markroot(x);tr[x].f=y;access(x);}
int sum;
void play(int x,int y)
{
if(!x)return ;
sum+=siz[x];
if(x!=y)siz[y]+=siz[x],fa1[x]=y;
play(tr[x].son[0],y);play(tr[x].son[1],y);
}
void lk(int x,int y)
{
sum=0;
if(findfa2(x)!=findfa2(y))
{
fa2[fa2[x]]=fa2[y];
link(x,y);
}
else
{
markroot(x);access(y);splay(y);
play(y,y);tr[y].son[0]=tr[y].son[1]=0;
}
}
int n,m,P;
int main()
{
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
scanf("%d%d%d",&n,&m,&P);
for(int i=1;i<=n;i++)fa1[i]=i,fa2[i]=i,siz[i]=1;
for(int i=1;i<=m;i++)
{
int x,y;scanf("%d%d",&x,&y);
x=findfa1(x);y=findfa1(y);
lk(x,y);
}
while(P--)
{
int x,y;scanf("%d%d",&x,&y);
x=findfa1(x);y=findfa1(y);
/* int uu=findfa(x),vv=findfa(y);
printf("%d ",getroot(uu));
printf("%d\n",getroot(vv));*/
lk(x,y);
if(sum==0)puts("No");
else printf("%d\n",sum);
}
return 0;
}