【SDOI2008】【BZOJ2049】Cave 洞穴勘測
Description
輝輝熱衷於洞穴勘測。某天,他依照地圖來到了一片被標記為JSZX的洞穴群地區。經過初步勘測,輝輝發現這片區域由n個洞穴(分別編號為1到n)以及若幹通道組成。而且每條通道連接了恰好兩個洞穴。
假如兩個洞穴能夠通過一條或者多條通道按一定順序連接起來,那麽這兩個洞穴就是連通的,按順序連接在一起的這些通道則被稱之為這兩個洞穴之間的一條路徑。洞穴都十分牢固無法破壞,然而通道不太穩定,時常由於外界影響而發生改變,比方。依據有關儀器的監測結果。123號洞穴和127號洞穴之間有時會出現一條通道,有時這條通道又會由於某種稀奇古怪的原因被毀。
輝輝有一臺監測儀器能夠實時將通道的每一次改變狀況在輝輝手邊的終端機上顯示:假設監測到洞穴u和洞穴v之間出現了一條通道,終端機上會顯示一條指令 Connect u v 假設監測到洞穴u和洞穴v之間的通道被毀,終端機上會顯示一條指令 Destroy u v 經過長期的艱苦卓絕的手工推算。輝輝發現一個奇怪的現象:不管通道怎麽改變,隨意時刻隨意兩個洞穴之間至多僅僅有一條路徑。因而,輝輝堅信這是由於某種本質規律的支配導致的。因而。輝輝更加夜以繼日地堅守在終端機之前,試圖通過通道的改變情況來研究這條本質規律。然而,最終有一天,輝輝在堆積成山的演算紙中崩潰了……他把終端機往地面一砸(終端機也足夠牢固無法破壞),轉而求助於你。說道:“你老兄把這程序寫寫吧”。
輝輝希望能隨時通過終端機發出指令 Query u v。向監測儀詢問此時洞穴u和洞穴v是否連通。
如今你要為他編敲代碼回答每一次詢問。已知在第一條指令顯示之前,JSZX洞穴群中沒有不論什麽通道存在。
Input
第一行為兩個正整數n和m,分別表示洞穴的個數和終端機上出現過的指令的個數。下面m行,依次表示終端機上出現的各條指令。每行開頭是一個表示指令種類的字符串s(”Connect”、”Destroy”或者”Query”。區分大寫和小寫),之後有兩個整數u和v (1≤u, v≤n且u≠v) 分別表示兩個洞穴的編號。
Output
對每一個Query指令。輸出洞穴u和洞穴v是否互相連通:是輸出”Yes”,否則輸出”No”。(不含雙引號)
Sample Input
例子輸入1 cave.in
200 5
Query 123 127
Connect 123 127
Query 123 127
Destroy 127 123
Query 123 127
例子輸入2 cave.in
3 5
Connect 1 2
Connect 3 1
Query 2 3
Destroy 1 3
Query 2 3
Sample Output
例子輸出1 cave.out
No
Yes
No
例子輸出2 cave.out
Yes
No
HINT
數據說明 10%的數據滿足n≤1000, m≤20000 20%的數據滿足n≤2000, m≤40000 30%的數據滿足n≤3000, m≤60000 40%的數據滿足n≤4000, m≤80000 50%的數據滿足n≤5000, m≤100000 60%的數據滿足n≤6000, m≤120000 70%的數據滿足n≤7000, m≤140000 80%的數據滿足n≤8000, m≤160000 90%的數據滿足n≤9000, m≤180000 100%的數據滿足n≤10000, m≤200000 保證全部Destroy指令將摧毀的是一條存在的通道本題輸入、輸出規模比較大,建議c\c++選手使用scanf和printf進行I\O操作以免超時
Source
動態樹
裸題啊…
link然後cut.查詢就查一下連通性…
(請叫我寫LCT必掛星人QAQ)
寫殘Cut就是切不掉那條邊233
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 10010
using namespace std;
int n,m,u,v;
char ch[20];
struct splay
{
int fa,ch[2];
bool rev;
}tree[MAXN];
int sta[MAXN],top;
void in(int &x)
{
char ch=getchar();int flag=1;x=0;
while (!(ch>=‘0‘&&ch<=‘9‘)) flag=ch==‘-‘?-1:1,ch=getchar();
while (ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();
}
inline bool is_root(int x)
{
return tree[tree[x].fa].ch[0]!=x&&tree[tree[x].fa].ch[1]!=x;
}
inline void push_down(int x)
{
if (tree[x].rev)
{
tree[x].rev^=1;tree[tree[x].ch[0]].rev^=1;tree[tree[x].ch[1]].rev^=1;
swap(tree[x].ch[0],tree[x].ch[1]);
}
}
inline void rot(int x)
{
int y=tree[x].fa,z=tree[y].fa,l,r;
l=(tree[y].ch[1]==x);r=l^1;
if (!is_root(y)) tree[z].ch[tree[z].ch[1]==y]=x;
tree[tree[x].ch[r]].fa=y;tree[y].fa=x;tree[x].fa=z;
tree[y].ch[l]=tree[x].ch[r];tree[x].ch[r]=y;
}
inline void Splay(int x)
{
sta[++top]=x;
for (int i=x;!is_root(i);i=tree[i].fa) sta[++top]=tree[i].fa;
while (top) push_down(sta[top--]);
while (!is_root(x))
{
int y=tree[x].fa,z=tree[y].fa;
if (!is_root(y))
{
if (tree[y].ch[0]==x^tree[z].ch[0]==y) rot(x);
else rot(y);
}
rot(x);
}
}
inline void access(int x)
{
for (int t=0;x;t=x,x=tree[x].fa) Splay(x),tree[x].ch[1]=t;
}
inline void make_root(int x)
{
access(x);Splay(x);tree[x].rev^=1;
}
inline void link(int x,int y)
{
make_root(x);tree[x].fa=y;
}
inline void cut(int x,int y)
{
make_root(x);access(y);Splay(y);tree[y].ch[0]=tree[x].fa=0;
}
inline int find(int x)
{
access(x);Splay(x);
int ret=x;
while (tree[ret].ch[0]) ret=tree[ret].ch[0];
return ret;
}
int main()
{
in(n);in(m);
while (m--)
{
scanf("%s",ch);in(u);in(v);
if (ch[0]==‘Q‘) find(u)==find(v)?puts("Yes"):puts("No");
if (ch[0]==‘C‘) link(u,v);
if (ch[0]==‘D‘) cut(u,v);
}
}
【SDOI2008】【BZOJ2049】Cave 洞穴勘測