CF1060E Sergey and Subway(公式推导+树上信息统计)
/* *author: zlc
*zucc_acm_lab *just do it *cf1060e *题意: *给出一张有n个节点的树形图G,若图上存在三个点u v,且满足u v之间距离为2,则可以在u v 之间连一条边 *询问此时所有点对之间的最短距离和 *考虑任意两点u v,若它们在原图上的距离s为偶数,则它们在新图上的距离为s/2 *若它们在原图上的距离为奇数,则它们在新图上的距离为(s+1)/2 *进一步推导可以得知答案的计算方法是 *(所有路径长度之和+奇数路径个数)/2 *所有路径长度之和,一遍DFS可做,这个做过很多次了 *考虑奇数路径数量 *如果u在奇数层,v在偶数层,那么就是奇数 *奇数路径数量就是奇数层的节点数*偶数层的节点数 */ #include<bits/stdc++.h> using namespace std; typedef long long ll; const double pi=acos(-1.0); const double eps=1e-6; const int mod=1e9+7; const int inf=1e9; const int maxn=2e5+100; inline int read () {int x=0;int f=1;char ch=getchar();while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}while (ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}return x*f;} ll qpow (ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;} vector<int> g[maxn]; int n; ll ans; ll d[2];//分别表示奇数层的节点数和偶数层的结点数 ll size[maxn]; void dfs (int u,int pre,int dep) { size[u]=1; d[dep%2]++; for (int v:g[u]) { if (v==pre) continue; dfs(v,u,dep+1); size[u]+=size[v]; } ans+=size[u]*(n-size[u]); } int main () { n=read(); for (int i=1;i<n;i++) { int x,y; x=read(); y=read(); g[x].push_back(y); g[y].push_back(x); } dfs(1,0,0); ans+=d[0]*d[1]; printf("%lld\n",ans/2); }