博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【树形dp练习】Y
阅读量:4968 次
发布时间:2019-06-12

本文共 1395 字,大约阅读时间需要 4 分钟。

题面

对于给定的树T,计算集合{A,B,C}的数量,其中:

1、A,B,C是树T的节点
2、不存在经过A,B,C的简单路径

分析

我猜题目叫Y的原因是因为要求的三个点构成一个Y的形状qvq

先看这个粉色的部分,考虑怎么计算第二部分的答案呢?

根据组合数学的思想,可以从3,4,8为根的子树内选两个(一个子树内只能选一个),然后再从除了以2为根的子树的其他所有结点中选一个,相乘。

第一部分的答案就更简单了,就是这个子树的所有小子树的大小的乘积,因为会被三次计算,所以最后除以三

然而!!

上面的方法过于复杂,我们可以根据正难则反的思想。计算三个点在一个简单路径上的数量,再用总路径数C(N,3)减去它。

三个点在一个简单路径:对于有儿子的点,选择他,并在以他为根的子树中选1个和除了他的子树以外的所有点中选1个

对于无儿子的点,除了他的所有点中选择2个。

最后因为每条路径被三个点计算了,总简单路径数除以3

代码

法一的代码。法二的代码更为简洁,可以自行实现

#include
#include
#include
#include
using namespace std;#define ll long long #define N 200010ll t,n,p1,p2,cnt;ll first[N],siz[N];struct email{ ll u,v; ll nxt;}e[N*4];inline void add(ll u,ll v){ e[++cnt].nxt=first[u];first[u]=cnt; e[cnt].u=u;e[cnt].v=v;}inline void init(){ cnt=p1=p2=0; memset(siz,0,sizeof(siz)); memset(first,0,sizeof(first)); }void dfs(ll u,ll fa){ ll mulv=0;siz[u]=1; for(ll i=first[u];i;i=e[i].nxt) { ll v=e[i].v; if(v==fa)continue; dfs(v,u); mulv+=(siz[u]-1)*(siz[v]); siz[u]+=siz[v]; } p1+=mulv*(n-siz[u]); for(ll i=first[u];i;i=e[i].nxt) { ll v=e[i].v; if(v==fa)continue; p2+=siz[v]*(mulv-siz[v]*(siz[u]-1-siz[v])); }}int main(){ while(scanf("%lld",&n)==1) { init(); for(ll i=1;i

 

转载于:https://www.cnblogs.com/NSD-email0820/p/9764985.html

你可能感兴趣的文章
mysql upper() 函数
查看>>
单片机复位电路
查看>>
php json_decode失败,返回null
查看>>
oracle 分页
查看>>
助教学期总结
查看>>
绘制基本 图形之矩形与多边形
查看>>
3-day3-list-truple-map.py
查看>>
Edit控件显示多行文字
查看>>
JS第二周
查看>>
dataTable.NET的search box每輸入一個字母進行一次檢索的問題
查看>>
Python 文件处理
查看>>
邻接表详解
查看>>
服务器一:分布式服务器结构
查看>>
迭代dict的value
查看>>
eclipse package,source folder,folder区别及相互转换
查看>>
Py 可能是最全面的 python 字符串拼接总结(带注释版)
查看>>
《Java程序设计实验》 软件工程18-1,3 OO实验2
查看>>
【Herding HDU - 4709 】【数学(利用叉乘计算三角形面积)】
查看>>
【7-9 有重复的数据I (20 分)】【此题卡输入,需要自己写个输入挂】
查看>>
JRebel安装部署,激活
查看>>