# 模板

#include<iostream>
#include<algorithm>
#include<cstring>

using namespace std;

const int N = 100010,M = N * 2;

//h是N个单链表的头节点
//ne是单链表的ne数组
//e是单个节点的值
//idx是当前可用的下标
//st是检查点有无走过
int e[M],ne[M],h[N];
int n,idx = 0;
bool st[N];

//单向联通
e[idx] = b;
ne[idx] = h[a];
h[a] = idx ++;
}

//深搜，遍历每一个点
void dfs(int u){
st[u] = true;

for(int i = h[u];i != -1;i = ne[i]){
int j = e[i];
if(!st[j]) dfs(j);
}
}

int main(){
cin >> n;

//点的状态初始化
memset(h,-1,sizeof h);

while(n --){
int a,b;
cin >> a >> b;

}

dfs(0);
}

##### 树的重心
#include<iostream>
#include<algorithm>
#include<cstring>

using namespace std;

const int N = 100010,M = N * 2;

int e[M],ne[M],h[N];
int idx = 0;
int st[M];
int n;

int ans = N;

e[idx] = b;
ne[idx] = h[a];
h[a] = idx ++;
}

int dfs(int u){
st[u] = 1;      //当前点走过

int sum = 1,res = 0;        //sum是该点的节点数，res是连通块内点的数量

//遍历一条树枝
for(int i = h[u];i != -1;i = ne[i]){
int j = e[i];           //取出子节点下标
if(!st[j]){
int t = dfs(j);     //算出子节点的节点数
sum += t;
res = max(res,t);
}
}

res = max(res,n - sum);     //取连通块节点最大值
ans = min(ans,res);

return sum;
}

int main(){
cin >> n;

memset(h,-1,sizeof h);         //点的状态初始化

for(int i = 1;i < n;i ++){
int a,b;
cin >> a >> b;