2019.06.28【NOIP提高组】模拟 A 组

T1:这一题我当场就想出正解了,但是因为C++自带快排函数的问题0分。

设s[i][j]表示第i组数有j个数和它相同的组的个数,这个可以用枚举位置+快排来求。

然后就是要对s进行去重。具体做法就是s[i][j]=s[i][j]-s[i][j+1]*(j+1)(j=5~0)。至于为什么要这样做,我们可以想一想,一个j长度+1的相同组就可以产生j+1个长度为j的相同组(C(j+1,j)=j+1),所以我们减去就好了。

总结:C++的快排要一个一个手动比较,不能用for循环。

 

T2:这题要先选一个唯一的根。具体做法就是找出树的直径(长度最长的链),然后如果直径的长度是奇数的话,那么root就为直径的中点,否则要新加一个点作为root,接着要把直径中间的两个点的连边断开,并把这两个点连向root。

确定了root之后,我们要把每一棵子树分类,同构的标相同的编号,不同的标不同的编号。具体做法就是bfs从下到上处理,每一次把这棵子树的所有儿子的编号记录下来,然后排序,并且判断一下之前有没有与其具有相同儿子序列的点,有就表上相同的号,否则就新建一个种类。

把所有子树都分好类之后我们就可以开始dp+网络流了。

还是从下到上做。设f[i][j]表示以i为根的子树与以j为根的子树匹配的最小代价。

注意:1、i和j要同构(编号相同)才能匹配。2、i和i是可以进行匹配的。

我们每次算i、j匹配的最小代价时,把i和j的所有儿子列成两列(形成一个二分图),然后把同构的儿子连上边(流量为1,费用为f[x][y],x是i的儿子,y是j的儿子)。然后建立源点和汇点,做一遍费用流。设最小费用为mi,那么f[i][j]=mi+(be[i]^fi[j])(be与fi分别为初始状态和密码状态)。最终的答案就是f[root][root]。

 

总结:1、为了排除一些简单错误,可以通过不停地用生成数据函数(make_data)、暴力程序和正解来对拍。

2、费用流反向弧的费用=正向弧的费用的相反数。不要忘记了。

 

T3:这题是一道复杂的计算几何。

首先我们知道两个点的管理范围的分界线就是它们的中垂线。所以我们要求出一个点的管理范围,那么就做出它与其他点的中垂线,然后求这些中垂线的半平面交。至于要求最小的被监视的人数,那么我们可以把管理范围有临边的两个点之间连边,设置离初始位置最近的点为起点,靠边界的点为终点,跑一遍最短路就行了。

至于求半平面交,具体见我的“向量”和“半平面交”这两篇博客。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值