1. 程式人生 > >2018.10.04 codeforces1060E. Sergey and Subway(樹形dp)

2018.10.04 codeforces1060E. Sergey and Subway(樹形dp)

傳送門 一開始把題意讀錯了。 我們dfs時對於邊(p,fa)(p,fa),計算出以pp為根的子樹對子樹外連通塊的貢獻,然後加上漏加的貢獻。 這樣算出來是答案的兩倍。 因為相當於dis(u,v)dis(u,v)dis(v,u)dis(v,u)的貢獻都被計入了答案。 程式碼:

#include<bits/stdc++.h>
#define N 200005
#define ll long long
using namespace std;
inline int read(){
	int ans=0;
	char ch=getchar();
	while
(!isdigit(ch))ch=getchar(); while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar(); return ans; } int n,cnt,first[N],tot[2],siz[N]; ll ans=0; struct edge{int v,next;}e[N<<1]; inline void add(int u,int v){e[++cnt].v=v,e[cnt].next=first[u],first[u]=cnt;} inline void dfs(int p,
int fa,int op){ siz[p]=1,++tot[op]; for(int i=first[p];i;i=e[i].next){ int v=e[i].v; if(v==fa)continue; dfs(v,p,op^1); siz[p]+=siz[v]; } ans+=1ll*siz[p]*(1ll*(n-siz[p])); } 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,0); cout<<
(ans+1ll*tot[0]*(1ll*tot[1])>>1); return 0; }