$(u,v,w)$合法,当且仅当存在一条从$u$到$v$的路径经过$w$(当然$u,v,w$仍要各不相同)
当$w_{1}$和$w_{2}$之间存在两条无公共边的路径,则$forall u,vin V,(u,v,w_{1})$和$(u,v,w_{2})$合法是等价的
相当于每一次加入一条边后,就将这条边所产生的环上的点缩起来,之后显然仍是一棵树,重复此过程,那么每一次都是对一棵树统计答案
用并查集以及维护若干信息即可,求lca时可以暴力向父亲移动,总复杂度即$o(n)$
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 100005 4 #define ll long long 5 struct Edge{ 6 int nex,to; 7 }edge[N<<1]; 8 vector<int>v1,v2; 9 int E,n,q,x,y,head[N],f[N],fa[N],vis[N],sz[N],Sz[N]; 10 ll ans,sum[N]; 11 ll sqr(int k){ 12 return 1LL*k*k; 13 } 14 ll calc(int k){ 15 return 1LL*sz[k]*(1LL*(sz[k]-1)*(n-2)+1LL*(n-1)*(n-sz[k])-sum[k]-sqr(n-Sz[k])); 16 } 17 int find(int k){ 18 if (k==fa[k])return k; 19 return fa[k]=find(fa[k]); 20 } 21 void merge(int x,int y){ 22 ans-=calc(y); 23 fa[y]=x; 24 sz[x]+=sz[y]; 25 sum[x]+=sum[y]; 26 } 27 void add(int x,int y){ 28 edge[E].nex=head[x]; 29 edge[E].to=y; 30 head[x]=E++; 31 } 32 void calc(int x,int y){ 33 x=find(x),y=find(y); 34 v1.clear(),v2.clear(); 35 int lca; 36 while (1){ 37 if (x){ 38 v1.push_back(x); 39 if (vis[x]){ 40 lca=x; 41 break; 42 } 43 vis[x]=1; 44 x=find(f[x]); 45 } 46 if (y){ 47 v2.push_back(y); 48 if (vis[y]){ 49 lca=y; 50 break; 51 } 52 vis[y]=1; 53 y=find(f[y]); 54 } 55 } 56 ans-=calc(lca); 57 for(int i=0;v1[i]!=lca;i++){ 58 merge(lca,v1[i]); 59 sum[lca]-=sqr(Sz[v1[i]]); 60 } 61 for(int i=0;v2[i]!=lca;i++){ 62 merge(lca,v2[i]); 63 sum[lca]-=sqr(Sz[v2[i]]); 64 } 65 ans+=calc(lca); 66 for(int i=0;i<v1.size();i++)vis[v1[i]]=0; 67 for(int i=0;i<v2.size();i++)vis[v2[i]]=0; 68 } 69 void dfs(int k,int fa){ 70 f[k]=fa; 71 Sz[k]=1; 72 for(int i=head[k];i!=-1;i=edge[i].nex) 73 if (edge[i].to!=fa){ 74 dfs(edge[i].to,k); 75 Sz[k]+=Sz[edge[i].to]; 76 sum[k]+=sqr(Sz[edge[i].to]); 77 } 78 } 79 int main(){ 80 scanf("%d",&n); 81 memset(head,-1,sizeof(head)); 82 for(int i=1;i<n;i++){ 83 scanf("%d%d",&x,&y); 84 add(x,y); 85 add(y,x); 86 } 87 dfs(1,0); 88 for(int i=1;i<=n;i++){ 89 fa[i]=i; 90 sz[i]=1; 91 ans+=calc(i); 92 } 93 printf("%lld ",ans); 94 scanf("%d",&q); 95 for(int i=1;i<=q;i++){ 96 scanf("%d%d",&x,&y); 97 calc(x,y); 98 printf("%lld ",ans); 99 } 100 }