题解:
后缀数组。
树上唯一的不同是第二关键字要先计数排序。
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ULL;
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
const int N=5e5+50, L=18;
const ULL base=31;
int n, fa[N][L+2], bin[L+2], dep[N], h[N];
ULL pw[N*2], g[N][L+2];
int sa[N*2], *rk=new int[N*2](), *rk2=new int[N*2]();
vector <int> edge[N];
inline void dfs(int x,int f) {
fa[x][0]=f; g[x][0]=edge[x].size(); rk[x]=g[x][0]; dep[x]=dep[f]+1;
for(int i=1;i<=L;i++) {
fa[x][i]=fa[fa[x][i-1]][i-1];
g[x][i]=g[x][i-1]*pw[bin[i-1]]+g[fa[x][i-1]][i-1];
}
for(int e=edge[x].size()-1;e>=0;e--) {
int v=edge[x][e]; if(v==f) continue;
dfs(v,x);
}
}
inline void Rsort() {
static int c[N], q[N];
for(int i=1;i<=n;i++) c[i]=0;
for(int i=1;i<=n;i++) c[rk2[i]]++;
for(int i=1;i<=n;i++) c[i]+=c[i-1];
for(int i=1;i<=n;i++) q[c[rk2[i]]--]=i;
for(int i=1;i<=n;i++) c[i]=0;
for(int i=1;i<=n;i++) c[rk[i]]++;
for(int i=1;i<=n;i++) c[i]+=c[i-1];
for(int i=n;i>=1;i--) sa[c[rk[q[i]]]--]=q[i];
}
inline int lcp(int x,int y) {
int xx=x, yy=y;
for(int i=L;i>=0;i--)
if(g[xx][i]==g[yy][i])
xx=fa[xx][i], yy=fa[yy][i];
return min(dep[x]-dep[xx],dep[y]-dep[yy]);
}
inline void build_sa() {
for(int i=0,q;i<=L;++i) {
for(int j=1;j<=n;j++) rk2[j]=rk[fa[j][i]];
Rsort(); swap(rk,rk2); rk[sa[1]]=q=1;
for(int j=2;j<=n;j++)
rk[sa[j]]=(rk2[sa[j]]==rk2[sa[j-1]] && rk2[fa[sa[j]][i]]==rk2[fa[sa[j-1]][i]]) ? q : ++q;
}
for(int i=2;i<=n;i++)
h[i]=lcp(sa[i-1],sa[i]);
}
int main() {
n=rd(); pw[0]=1;
for(int i=0;i<=L;i++) bin[i]=1<<i;
for(int i=1;i<N*2;++i) pw[i]=pw[i-1]*base;
for(int i=1;i<n;i++) {
int x=rd(), y=rd();
edge[x].push_back(y);
edge[y].push_back(x);
}
dfs(1,0);
build_sa();
long long ans=0;
for(int i=1;i<=n;i++)
ans+=dep[sa[i]]-h[i];
cout<<ans<<endl;
}