# bzoj2815: [ZJOI2012]災難

n<=65534

lca啊（霧）！

## 代碼：

``````/*************************************************************
Problem: bzoj 2815 [ZJOI2012]災難
User: fengyuan
Language: C++
Result: Accepted
Time: 212 ms
Memory: 17452 kb
Submit_Time: 2018-01-24 19:34:32
*************************************************************/

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cctype>
#include<cstdlib>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;

char ch = getchar(); ll x = 0; int op = 1;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') op = -1;
for(; isdigit(ch); ch = getchar()) x = x*10+ch-'0';
return x*op;
}
inline void write(ll a) {
if(a < 0) putchar('-'), a = -a;
if(a >= 10) write(a/10); putchar('0'+a%10);
}

const int N = 100000, M = 200010;
int n, cnt, tot;
struct edge {
int to, nxt;
edge() {}
edge(int x, int y) { to = x, nxt = y; }
}e[M], t[M];

inline void tp() {
queue<int> q;
for(int i = 1; i <= n; i ++) if(!in[i]) q.push(i);
while(!q.empty()) {
int u = q.front(); q.pop(); q2[++ tot] = u;
for(int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to; in[v] --;
if(!in[v]) q.push(v);
}
}
}
inline int lca(int x, int y) {
if(x == -1) return y;
if(depth[x] < depth[y]) swap(x, y);
int tmp = depth[x] - depth[y];
for(int i = 20; i >= 0; i --) if(tmp>>i&1) x = f[x][i];
if(x == y) return x;
for(int i = 20; i >= 0; i --)
if(f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
return f[x][0];
}
inline void build() {
for(int i = tot; i >= 1; i --) {
int u = q2[i], fa = -1;
for(int j = head[u]; j; j = e[j].nxt) fa = lca(fa, e[j].to);
if(fa == -1) fa = 0; addtree(fa, u); vis[u] = 1;
depth[u] = depth[fa] + 1;
f[u][0] = fa;
for(int i = 1; 1<<i <= depth[u]; i ++) f[u][i] = f[f[u][i-1]][i-1];
}
}
inline void dfs(int u) {
sz[u] = 1;
for(int i = headt[u]; i; i = t[i].nxt) {
int v = t[i].to; dfs(v);
sz[u] += sz[v];
}
}
int main() {