点分治
非容斥方法
struct Edge {
int to, net;
}edge[maxn * 2];
int head[maxn], cnt;
int n, k;
int dis[maxn], arr[maxn], sz[maxn], msz[maxn], tail, all, rt;
bool vis[maxn];
void init() {
for(int i = 0; i <= n; i++) {
head[i] = -1;
vis[i] = 0;
}
cnt = 0;
}
void addedge(int u, int v) {
edge[cnt] = (Edge){v, head[u]};
head[u] = cnt++;
}
void Findrt(int pos, int pre) {
sz[pos] = 1;
msz[pos] = 0;
for(int i = head[pos]; i != -1; i = edge[i].net) {
int to = edge[i].to;
if(to == pre || vis[to]) continue;
Findrt(to, pos);
sz[pos] += sz[to];
msz[pos] = max(msz[pos], sz[to]);
}
msz[pos] = max(msz[pos], all - sz[pos]);
if(msz[pos] < msz[rt] || rt == 0) rt = pos;
}
void dfs(int pos, int pre, int v) {
arr[++tail] = v; //先保存下来
for(int i = head[pos]; i != -1; i = edge[i].net) {
int to = edge[i].to;
if(vis[to] || to == pre) continue;
dfs(to, pos, v);
}
}
void query(int x) {
}
void add(int x) {
}
void divide(int pos) {
vis[pos] = 1;
for(int i = head[pos]; i != -1; i = edge[i].net) {
int to = edge[i].to;
if(vis[to]) continue;
tail = 0;
dfs(to, pos, v);
for(int j = 1; j <= tail; j++) //先算对答案贡献
query(j);
for(int j = 1; j <= tail; j++) //再加入值
add(j)
}
//清空影响
for(int i = head[pos]; i != -1; i = edge[i].net) {
int to = edge[i].to;
if(vis[to]) continue;
tail = 0;
dfs(to, pos, 0);
}
//到下一层
for(int i = head[pos]; i != -1; i = edge[i].net) {
int to = edge[i].to;
if(vis[to]) continue;
all = sz[to];
rt = 0;
Findrt(to, 0);
divide(rt);
}
}
int main() {
cin >> n;
init();
for(int i = 1; i < n; i++) {
int u, v;
cin >> u >> v;
addedge(u, v);
addedge(v, u);
}
all = n;
rt = 0;
Findrt(1, 0);
divide(rt);
//接下来输出
return 0;
}