1. 程式人生 > 實用技巧 >CF1060E Sergey and Subway(公式推導+樹上資訊統計)

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); }