# BZOJ 2049 [Sdoi2008]Cave 洞穴勘测 | LCT

“这道题我**怎么A过？！”

BZOJ 2049

## 题解

#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <ctime>
#include <cstdlib>
using namespace std;
typedef unsigned long long ll;
#define enter putchar('\n')
#define space putchar(' ')
template <class T>
char c;
bool op = 0;
while(c = getchar(), c > '9' || c < '0')
if(c == '-') op = 1;
x = c - '0';
while(c = getchar(), c >= '0' && c <= '9')
x = x * 10 + c - '0';
if(op) x = -x;
}
template <class T>
void write(T x){
if(x < 0) putchar('-'), x = -x;
if(x >= 10) write(x / 10);
putchar('0' + x % 10);
}

const int N = 10005;
int n, m;
int fa[N], ls[N], rs[N];
bool rev[N];
#define which(u) (ls[fa[u]] == (u))
#define isroot(u) (!fa[u] || (ls[fa[u]] != (u) && rs[fa[u]] != (u)))

void rotate(int u){
int v = fa[u], w = fa[v], b = which(u) ? rs[u] : ls[u];
if(!isroot(v)) (which(v) ? ls[w] : rs[w]) = u;
which(u) ? (ls[v] = b, rs[u] = v) : (rs[v] = b, ls[u] = v);
fa[u] = w, fa[v] = u;
if(b) fa[b] = v;
}
void pushdown(int u){
if(!rev[u]) return;
rev[ls[u]] ^= 1;
rev[rs[u]] ^= 1;
swap(ls[u], rs[u]);
rev[u] = 0;
}
void splay(int u){
static int stk[N], top;
stk[top = 1] = u;
while(!isroot(stk[top])) stk[top + 1] = fa[stk[top]], top++;
while(top) pushdown(stk[top--]);
while(!isroot(u)){
if(!isroot(fa[u])){
if(which(u) == which(fa[u])) rotate(fa[u]);
else rotate(u);
}
rotate(u);
}
}
void access(int u){
int v = 0;
while(u){
splay(u);
rs[u] = v;
v = u;
u = fa[u];
}
}
void makeroot(int u){
access(u);
splay(u);
rev[u] ^= 1;
}
int findroot(int u){
access(u);
splay(u);
while(pushdown(u), ls[u]) u = ls[u];
splay(u);
return u;
}
makeroot(v);
fa[v] = u;
}
void cut(int u, int v){
makeroot(u);
access(v);
splay(v);
ls[v] = fa[u] = 0;
}

int main(){