CF1060E Sergey and Subway
阿新 • • 發佈:2020-11-30
CF1060E Sergey and Subway
統計邊的貢獻
先不考慮題中的重連邊,顯然求得就是樹上任意兩點距離和,按邊計貢獻,\(dfs\)一遍搞個\(siz\)就行
然後對於重連邊,顯然是偶數距離的會都重複計算,所以都要除以二,答案就是 偶數距離的/2+奇數距離的
然後可以方便先計算樹上任意兩點距離和,然後減去奇數距離的
#include <cstdio> #include <cstring> #include <cctype> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; const int N=200005; inline int read() { int x=0,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 f*x; } int n; int hd[N],to[N<<1],nxt[N<<1],tot; inline void add(int x,int y) { to[++tot]=y;nxt[tot]=hd[x];hd[x]=tot; } int dep[N],siz[N]; void dfs(int x,int f) { siz[x]=1; dep[x]=dep[f]+1; for(int i=hd[x];i;i=nxt[i]) { int y=to[i]; if(y==f) continue; dfs(y,x); siz[x]+=siz[y]; } } int main() { n=read(); for(int i=1;i<n;i++) { int u=read(),v=read(); add(u,v);add(v,u); } dfs(1,0); ll ans=0,c=0;//c是奇數點的數量 for(int i=1;i<=n;i++) { ans+=(ll)siz[i]*(n-siz[i]); if(dep[i]&1) c++; } ll k=c*(n-c); ans=(ans-k)/2+k; printf("%lld\n",ans); return 0; }