这个就有一点难想了。建图找父亲和子树大小,并设 f(x)=x≤mexf(x)=x\le mexf(x)=x≤mex 的个数,以0为根,则可以暴力计算f(0)。
遍历1~n-1,若其尚未被加入,则加入这个点及其所有祖先,并维护路径若x已经加入,f(x)=f(x-1),否则暴力更新。
code:
#include <bits/stdc++.h>
using namespace std;
long long n, sze[200005], a[200005], f[200005], da = 0, cnt = 0, l = 0, r = 0;
vector<long long> g[200005];
void dfs(long long u, long long fa){
sze[u] = 1;
f[u] = fa;
for(auto v : g[u]){
if(v==fa){
continue;
}
dfs(v, u);
sze[u] += sze[v];
if(!u){
da -= sze[v] * (sze[v] + 1) / 2;
}
}
}
int main(){
scanf("%lld", &n);
for(int i = 1;i<=n - 1;i++){
long long x, y;
scanf("%lld %lld", &x, &y);
g[x].push_back(y);
g[y].push_back(x);
}
da = n * (n + 1) / 2;
dfs(0, 0);
a[0] = 1;
for(int i = 1;i<=n - 1;i++){
if(!a[i]){
int x = f[i], son = i;
a[i] = 1;
while(!a[x]){
a[x] = 1;
son = f[son];
x = f[x];
}
if(x!=l&&x!=r){
break;
}
if(x==l){
l = i;
}else{
r = i;
}
if(!x){
sze[x] -= sze[son];
}
cnt = sze[l] * sze[r];
}
da += cnt;
}
printf("%lld", da);
return 0;
}
1335

被折叠的 条评论
为什么被折叠?



