Surgey and subway
先
列
式
子
,
∑
i
=
1
n
∑
j
=
1
n
d
i
s
(
i
,
j
)
=
∑
i
=
1
n
∑
j
=
1
n
⌈
d
i
s
t
(
i
,
j
)
2
⌉
=
∑
i
=
1
n
∑
i
=
1
n
(
d
i
s
t
(
i
,
j
)
+
[
d
i
s
(
i
,
j
)
m
o
d
2
=
=
0
]
/
2
)
]
先列式子,\sum_{i=1}^n\sum_{j=1}^ndis(i,j)=\sum_{i=1}^n\sum_{j=1}^n \left\lceil \dfrac{dist(i,j)}{2}\right\rceil=\sum_{i=1}^n\sum_{i=1}^n (dist(i,j)+[dis(i,j)mod2==0]/2)]
先列式子,∑i=1n∑j=1ndis(i,j)=∑i=1n∑j=1n⌈2dist(i,j)⌉=∑i=1n∑i=1n(dist(i,j)+[dis(i,j)mod2==0]/2)]
然后求一下和就行了
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
const int N=2e5+5;int n;
ll ans=0;
struct mess{
int link,v;
}q[N<<1];
int cnt=0,dep=1,head[N],in[N],size[N],cnt0=0,cnt1=0,root;
void put(int u,int v){q[++cnt].v=v;q[cnt].link=head[u];head[u]=cnt;}
void dfs(int s,int fa){
size[s]++;
if(dep%2) cnt1++;
if(dep%2==0) cnt0++;
for(int i=head[s];i;i=q[i].link)
{
int v=q[i].v;
if(v==fa) continue;
dep++;
dfs(v,s);
size[s]+=size[v];
dep--;
}
}
void dfs2(int s,int fa){
for(int i=head[s];i;i=q[i].link){
int v=q[i].v;
if(v==fa) continue;
ans+=(1ll*size[v]*(n-size[v]));
dfs2(v,s);
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
put(u,v),put(v,u);
in[v]++;
}
for(int i=1;i<=n;i++) if(!in[i]) {root=i;break;}
dfs(root,0);
dfs2(root,0);
ans+=1ll*cnt0*cnt1;
printf("%lld",ans/2);
}