链接:https://ac.nowcoder.com/acm/contest/5669/I
来源:牛客网
题意:每个样例中,n个数字,m个团,S是个概率,
这n个数字均属于且唯一属于m个团中的一个(be数组),a[i][j]代表i与j是否属于同一个团(1是0否),
对于每一个a[i][j],有1/S的概率将值修改(1变成0,0变成1).
现在给你n,S与二维数组a,求最可能的be数组,按照字典序输出.
给了这么个数据生成器,
数据范围:30≤n≤300,20≤S≤100 ,
给你数据的方式是
(0,1),(0,2)…(0,n-1),(1,2) … (n-3,n-1),(n-2,n-1)(0,1),(0,2)…(0,n−1),(1,2)…(n−3,n−1),(n−2,n−1).顺序
的01串
思路:s>=20,这就说明被修改的边会很少,那么我们先遍历一边数组,对每个还没有标记为某个团的人,先将所有人的权值初始化为0,将他与和他有边的所有人都压入一个数组中,对数组中的每个人,将所有与这个人相连的人的权值+1,将权值大的数字计为同一个团.
比如i还没有标记为某个团,记录所有和i有边的j为一个数组 [ j0,j1,j2…,n ] (i也要加入),对所有k满足 a[j][k]==1 将k的权值++(存在多个j则权值重复计算),当k的权值过了一个阀值,则将其加入i所在的团.
这个做法的依据是s很大,那么若一个数字s与i并不在同一个团,s与i所在团的点的边就会很少,这种操作计算出来的权值会呈现两级化的状态.
那么阀值取多少合适呢?
这是一个玄学的东西(我不会算),比赛时是用2/5*最大权值过的,结束后发现有些人用的是与i相连的边的一半,结束后我测试了一下 (4000/10000~4999/10000)*最大权值 范围内都可以,不知道是怎么算出来的,而且ac的代码中和s没啥关系,哪位概率大神能有证明的方法欢迎在评论区贴出来.
队友代码(FFFF就是那个阀值):
#define FFFF *4000/10000
#pragma comment(linker, "/STACK:102400000,102400000")
//#include
#include
#include
#include
#include
#include
#include
#include
#include