description
在遙遠的s星系中一共有n個星球,編號為1…n。其中的一些星球決定組成聯盟,以方便相互間的交流。但是,組成聯盟的首要條件就是交通條件。初始時,在這n個星球間有m條太空隧道。每條太空隧道連線兩個星球,使得它們能夠相互到達。若兩個星球屬於同乙個聯盟,則必須存在一條環形線路經過這兩個星球,即兩個星球間存在兩條沒有公共隧道的路徑。為了壯大聯盟的隊伍,這些星球將建設p條新的太空隧道。這p條新隧道將按順序依次建成。一條新軌道建成後,可能會使一些星球屬於同乙個聯盟。你的任務是計算出,在一條新隧道建設完畢後,判斷這條新軌道連線的兩個星球是否屬於同乙個聯盟,如果屬於同乙個聯盟就計算出這個聯盟中有多少個星球。
這道題也很強啊,像我這樣的蒟蒻就只會判no……思路大概是這樣的:f[
0][x
] f[0
][x]
表示x x
所在的連通塊是什麼(就是並查集的東西),f[
1][x
]' role="presentation" style="position: relative;">f[1
][x]
f[1]
[x]表示
x x
實際上代表的是哪乙個點,然後對於每次連邊,若不在同乙個連通塊,那顯然輸出no就可以了,然後在lct上連邊;否則就把兩點間的點都縮為乙個點,具體的方法是暴力搞……但是由於每個點只會被縮一次,所以時間複雜度是***的。
#include
using
namespace
std;
#define ll long long
#define pa pair
const
int maxn=200010;
const
int inf=2147483647;
int read()
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return x*f;
}int n,m,p;
int f[2][maxn];//f[0]為並查集關係 f[1]為這個點實際上是什麼點
int findfa(int o,int x)
int fa[maxn],son[maxn][2],rev[maxn],size[maxn];
void down(int x)
}bool is(int x)
void rotate(int x)
int sta[maxn],top;
void update(int x)
void splay(int x)
}void access(int x)
}void make_root(int x)
void split(int x,int y)
void link(int x,int y)
void dfs(int x,int rt)
void link(int x,int y,int type)
split(x,y);
dfs(y,y);
son[y][0]=son[y][1]=0;
if(type)printf("%d\n",size[y]);
}int main()
bzoj4998 LCT 並查集 星球聯盟
description 在遙遠的s星系中一共有n個星球,編號為1 n。其中的一些星球決定組成聯盟,以方便相互間的交流。但是,組成 聯盟的首要條件就是交通條件。初始時,在這n個星球間有m條太空隧道。每條太空隧道連線兩個星球,使得它們能 夠相互到達。若兩個星球屬於同乙個聯盟,則必須存在一條環形線路經過這...
bzoj4998 星球聯盟(並查集 邊雙)
傳送門 總算有自己的 bzoj 賬號啦!話說這題好像 scape 去年暑假就講過 然而我到現在才會 lct 什麼的跑得太慢了而且我也不會,所以這裡是乙個並查集的做法 首先題目意思就是要我們動態維護點雙 我們離線,先求出乙個森林,並且要使用編號盡量小的邊 連上一條邊的時候,如果它們還沒有聯通,那麼顯然...
bzoj4998 星球聯盟
description 在遙遠的s星系中一共有n個星球,編號為1 n。其中的一些星球決定組成聯盟,以方便相互間的交流。但是,組成 聯盟的首要條件就是交通條件。初始時,在這n個星球間有m條太空隧道。每條太空隧道連線兩個星球,使得它們能 夠相互到達。若兩個星球屬於同乙個聯盟,則必須存在一條環形線路經過這...