[bzoj4998][LCT][並查集]星球聯盟
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;}
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;
}