2018.10.04 codeforces1060E. Sergey and Subway(树形dp)

版权声明:随意转载哦......但还是请注明出处吧: https://blog.csdn.net/dreaming__ldx/article/details/82940766

传送门
一开始把题意读错了。
我们dfs时对于边 ( p , f a ) (p,fa) ,计算出以 p p 为根的子树对子树外连通块的贡献,然后加上漏加的贡献。
这样算出来是答案的两倍。
因为相当于 d i s ( u , v ) dis(u,v) d i s ( 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;
}

猜你喜欢

转载自blog.csdn.net/dreaming__ldx/article/details/82940766