[cf855G]Harry Vs Voldemort

$(u,v,w)$合法,当且仅当存在一条从$u$到$v$的路径经过$w$(当然$u,v,w$仍要各不相同)

当$w_{1}$和$w_{2}$之间存在两条无公共边的路径,则$\forall u,v\in 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\n",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\n",ans);
 99     }
100 }
View Code

 

posted @ 2021-05-27 14:45  PYWBKTDA  阅读(67)  评论(0编辑  收藏  举报