Time Limit: 10 Sec Memory Limit: 256 MB
Submit: 440 Solved: 215
Description
1946 年 3 月 5 日,英國前首相溫斯頓·丘吉爾在美國富爾頓發表“鐵
幕演說”,正式拉開了冷戰序幕。
美國和蘇聯同爲世界上的“超級大國”,爲了爭奪世界霸權,兩國及其
盟國展開了數十年的鬥爭。在這段時期,雖然分歧和衝突嚴重,但雙方都
盡力避免世界範圍的大規模戰爭(第三次世界大戰)爆發,其對抗通常通
過局部代理戰爭、科技和軍備競賽、太空競爭、外交競爭等“冷”方式進
行,即“相互遏制,不動武力”,因此稱之爲“冷戰”。
Reddington 是美國的海軍上將。由於戰爭局勢十分緊張,因此他需要
時刻關注着蘇聯的各個活動,避免使自己的國家陷入困境。蘇聯在全球擁
有 N 個軍工廠,但由於規劃不當,一開始這些軍工廠之間是不存在鐵路
的,爲了使武器製造更快,蘇聯決定修建若干條道路使得某些軍工廠聯通。
Reddington 得到了蘇聯的修建日程表,並且他需要時刻關注着某兩個軍工
廠是否聯通,以及最早在修建哪條道路時會聯通。具體而言,現在總共有
M 個操作,操作分爲兩類:
• 0 u v,這次操作蘇聯會修建一條連接 u 號軍工廠及 v 號軍工廠的鐵
路,注意鐵路都是雙向的;
• 1 u v, Reddington 需要知道 u 號軍工廠及 v 號軍工廠最早在加入第
幾條條鐵路後會聯通,假如到這次操作都沒有聯通,則輸出 0;
作爲美國最強科學家, Reddington 需要你幫忙設計一個程序,能滿足
他的要求。
Input
第一行兩個整數 N, M。
接下來 M 行,每行爲 0 u v 或 1 u v 的形式。
數據是經過加密的,對於每次加邊或詢問,真正的 u, v 都等於讀入的
u, v 異或上上一次詢問的答案。一開始這個值爲 0。
1 ≤ N, M ≤ 500000,解密後的 u, v 滿足1 ≤ u, v ≤ N, u不等於v
Output
對於每次 1 操作,輸出 u, v 最早在加入哪條邊後會聯通,若到這個操
作時還沒聯通,則輸出 0。
Sample Input
5 9
0 1 4
1 2 5
0 2 4
0 3 4
1 3 1
0 7 0
0 6 1
0 1 6
1 2 6
Sample Output
0
3
5
HINT
Source
dalao講解
顯然,我們只需要按秩合併就可以了,我們記錄一個size即可,然後查詢這條路徑上的最大值,表示這次操作之後就聯通了
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int MAXN = 500005;
int N, M, fa[MAXN], sz[MAXN], tim[MAXN], timer, opt, u, v, last;
int find( int x ) {
if( x == fa[x] ) return x;
else return find(fa[x]);
}
void add_line( int x, int y ) {
x = find(x), y = find(y);
if( x == y ) return;
else {
if( sz[x] < sz[y] ) swap( x, y );
tim[y] = timer;
sz[x] = sz[x] + sz[y];
fa[y] = x;
}
}
int get_dep( int x ) {
int cnt = 0;
while( fa[x] != x ) {
x = fa[x];
cnt++;
}
return cnt;
}
void query( int x, int y ) {
int fax = find(x), fay = find(y);
if( fax != fay ) { printf( "0\n" ); last = 0; return; }
int depx = get_dep(x), depy = get_dep(y);
if( depx < depy ) {
swap( x, y );
swap( depx, depy );
}
int tmp = 0;
while( depx != depy ) {
if( tmp < tim[x]) tmp = tim[x];
depx--; x = fa[x];
}
while( x != y ) {
if( tmp < tim[x] ) tmp = tim[x];
if( tmp < tim[y] ) tmp = tim[y];
x = fa[x]; y = fa[y];
}
printf( "%d\n", tmp );
last = tmp;
}
int main( ) {
scanf( "%d%d", &N, &M ); last = 0;
for( register int i = 1; i <= N; i++ ) sz[i] = 1;
for( register int i = 1; i <= N; i++ ) fa[i] = i;
for( register int i = 1; i <= M; i++ ) {
scanf( "%d%d%d", &opt, &u, &v );
u = u ^ last, v = v ^ last;
if( opt == 0 ) { timer++; add_line( u, v ); }
else query( u, v );
}
return 0;
}