【思路】
将两棵树重心相连,做树形DP
易得
Down[now]=∑Down[son]+Size[son]
Up[son]=Up[now]+Size[1]-Size[son]*2+Down[now]-Down[son]
初始化:Up[1]=0
【注意事项】
1.部分数据在JZ的辣鸡电脑上跑会爆栈,交到OJ就可以了
2.什么?你不会求重心?
https://oi-wiki.org/graph/tree-centroid/
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<string> 5 #include<cstring> 6 using namespace std; 7 int n1,n2,m,h[300005],g[300005],wd[600005],c[6000005],dis[600005]; 8 int wnt,cnt,tot,rt1,rt2,wt[300005],size[600005],fa[600005]; 9 int x1[600005],x2[600005],y1[600005],y2[600005]; 10 long long up[6000005],down[6000005]; 11 long long ans; 12 struct node 13 { 14 int next,to; 15 }e[6000005],f[6000005],w[2000005]; 16 void add(int x,int y) 17 { 18 e[++cnt].to=y; 19 e[cnt].next=h[x]; 20 h[x]=cnt; 21 } 22 void odd(int x,int y) 23 { 24 f[++tot].to=y; 25 f[tot].next=g[x]; 26 g[x]=tot; 27 } 28 void add_edge(int x,int y) 29 { 30 w[++wnt].to=y; 31 w[wnt].next=wd[x]; 32 wd[x]=wnt; 33 } 34 void get1(int x,int fa) 35 { 36 size[x]=1; 37 wt[x]=0; 38 for(int i=h[x];i;i=e[i].next) 39 { 40 int y=e[i].to; 41 if(y!=fa) 42 { 43 get1(y,x); 44 size[x]+=size[y]; 45 wt[x]=max(wt[x],size[y]); 46 } 47 } 48 wt[x]=max(wt[x],n1-size[x]); 49 if(rt1==0||wt[x]<wt[rt1])rt1=x; 50 } 51 void get2(int x,int fa) 52 { 53 size[x]=1; 54 wt[x]=0; 55 for(int i=g[x];i;i=f[i].next) 56 { 57 int y=f[i].to; 58 if(y!=fa) 59 { 60 get2(y,x); 61 size[x]+=size[y]; 62 wt[x]=max(wt[x],size[y]); 63 } 64 } 65 wt[x]=max(wt[x],n2-size[x]); 66 if(rt2==0||wt[x]<wt[rt2])rt2=x; 67 } 68 void dfs(int x) 69 { 70 size[x]=1; 71 for(int i=wd[x];i;i=w[i].next) 72 { 73 int y=w[i].to; 74 if(fa[x]!=y) 75 { 76 fa[y]=x; 77 dfs(y); 78 size[x]+=size[y]; 79 down[x]+=down[y]+size[y]; 80 } 81 } 82 } 83 void bfs(int x) 84 { 85 int head=0,tail=1;c[1]=1; 86 while(head<tail) 87 { 88 int x=c[++head]; 89 if(x==1)up[x]=0; 90 else up[x]=up[fa[x]]+size[1]-size[x]+down[fa[x]]-down[x]-size[x]; 91 for(int i=wd[x];i;i=w[i].next) 92 { 93 int y=w[i].to; 94 if(fa[x]!=y) 95 { 96 c[++tail]=y; 97 } 98 } 99 } 100 } 101 int main() 102 { 103 freopen("unite.in","r",stdin); 104 freopen("unite.out","w",stdout); 105 scanf("%d%d",&n1,&n2); 106 for(int i=1,x,y;i<n1;i++) 107 { 108 scanf("%d%d",&x1[i],&y1[i]); 109 add(x1[i],y1[i]); 110 add(y1[i],x1[i]); 111 } 112 for(int i=1,x,y;i<n2;i++) 113 { 114 scanf("%d%d",&x2[i],&y2[i]); 115 odd(x2[i],y2[i]); 116 odd(y2[i],x2[i]); 117 } 118 get1(1,0); 119 get2(1,0); 120 for(int i=1,x,y;i<n1;i++) 121 { 122 add_edge(x1[i],y1[i]); 123 add_edge(y1[i],x1[i]); 124 } 125 for(int i=1,x,y;i<n2;i++) 126 { 127 add_edge(x2[i]+n1,y2[i]+n1); 128 add_edge(y2[i]+n1,x2[i]+n1); 129 } 130 add_edge(rt1,rt2+n1); 131 m=n1+n2; 132 dfs(1); 133 bfs(1); 134 for(int i=1;i<=m;i++) 135 { 136 ans+=up[i]+down[i]; 137 } 138 printf("%lld ",ans/2); 139 fclose(stdin);fclose(stdout); 140 }