华为软件精英挑战赛-2020-初赛复赛-题目分析/算法Baseline (求出有向图中所有的环)

2020.06.01更新:

开源比赛代码


题意:给定一个有向图,求出图中所有长度在[3,7]之间的环。

输入:格式为[IDU,IDV,Weight]的边表,ID为32位无符号整数(当然题目说明了,小于2^31,所以int32就好),边最多28W条,不重复,结点平均度数小于10。环中同一个ID不可以重复出现(若大环包括小环,则需要分开统计),环的个数不大于300W。

输出:环的个数,按照1.环长度;2.环的数字字典序输出所有环。

举个例子:1,2,3的全连通图有两个环

初步思路:

  • 要避免搜索出的路径重复,需要制定一个环的标准型,以题目为例,就是最小的ID在环表示的首位
  • 题目要求最小的结点在每个路径的第一位,故对ID排序后,重映射所有结点序号为[0,n),在搜索时,如果直接对某个结点的出边从小到大搜索,最后得到的答案自然是排好序的(虽然排序一遍答案花掉的时间也不多)
  • 用拓扑排序删去一部分点(入度为0,或出度为0的点可以删去,直到没有满足条件的点)
  • 搜索,剪枝(深度在3-7之间、每次访问的结点ID都应该大于起点的ID),这里有很大的优化空间
  • 关于换行应该是CRLF(\r\n)还是LF(\n),官方表示都没有关系

先贴一个在100万环【E28W N30000 A1004812】的数据集上要跑几分钟的Baseline(复赛中相邻边权的if判断自己加上吧)

上分小窍门:

  • 群消息收益占比 60%
    自己优化收益 30%
    服务器抖动收益 10%
  • XJBG收益 100%
  • 吃瓜 999%
  • magic 1000%

初赛基本方案与成绩:

方案:正4步负3步DFS,按照28Wx50适配

成绩(我太菜了):0.211


复赛题目差异:

  • 转账记录 28W -> 200W
  • 环个数 2914186 -> 2000W
  • 转账金额比例约束 :如[A,B,X],[B,C,Y],要满足0.2 <= Y/X <= 3
  • ID为32位的无符号整数,转账金额为32位的正整数,且都小于2的31次方,选手可以不用考虑范围之外的输入。(转账金额不为0的意思,但所有数据依然为int32范围)
  • 去除了平均转账记录数< 10的说明
  • (你就是这么用第三个数据的???)
  • (为什么转账记录x7,环的个数也才x7,有一种291W复制粘贴几次的赶脚)

复赛规则差异:

  • 每天3次,AB榜,最后一天下午更换数据集,且对题目进行调整(喵喵喵???),可提交5次
  • 禁止直接根据ID和权重的取值排除部分数据,禁止跳过文件中的部分数据


水群的快乐>打其他比赛的快乐>>造数据的快乐

提供初赛几组数据的复赛结果,仅供参考:

  • [56]->[41]
  • [3512444]->[697518]
  • [38252]->[9153]
  • [2861665]->[639096]

鉴于要结果的同学太多了,发布一个复赛baseline(慢到家了):

暴力对表程序,仅限挂机拿手环使用,跑出Family群( 原热身赛1群,群号974891831)中1963W随机图的时间约一小时,跑初赛数据约8分钟。


200512.比赛结束前的最后一次更新:

0509官方更新了A榜使用的数据集,就目前的结果来看,在线的数据分布应该是菊花图、随机图、完全图的组合(没验证过,没啥意思)。交易金额没有明确表示是否存在0,但是在线数据在环中不存在两次连续0的转账记录。

之前造1963W数据的策略为:

  • 转账金额随机正整数
  • 结点ID为[0,111314)全覆盖,转账记录数为200W
  • 转入与转出概率相等
  • 6000,25123开始的连续ID分别组成K13
  • 10000开始的连续ID组成K14
  • 剩余边按照上述描述随机生成

生成随机图与完全图并不难,简单说一下生成无标度网络的一种方法(参考networkx):

  • 假定每次加入一个新的结点和一定数量的边(通过概率比例调整,见例),当现有结点有越高的度时,其与新加入结点连接的概率越高
  • 每次按照alpha+beta的概率产生一个新结点并连一条边
  • 按照gamma的概率在旧的结点之间连一条边
  • 满足alpha+beta+gamma=1,alpha表示按照入度分布连边(入度占总入度比越高的点越容易被选中),beta表示按照出度分布,gamma表示按照入度和出度分布
  • 说明:假定按照入度选中的点为v,按照出度选中的点为u,新结点为x,边权重为w,则每次有alpha概率产生[x,v,w],有beta概率产生[u,x,w],有gamma概率产生[u,v,w]
  • 重复上述步骤直到边数满足要求
  • 例:结点N=100,边E=500,则alpha+beta=0.2,gamma=0.8
  • 不可以有自环,边权为随机正整数
  • 为了避免ID集中在某个范围,在int32范围内做ID重映射


复赛成绩/总结(2020.05.16):

方案:正4步负4步DFS,按照题目给定范围适配

成绩:2.8213

这比赛好迷呀,之前花了这么久,对问题做了尽可能好的(划掉,就是暴力DFS嘛)适配,代码已经特化到很难修改了。下午改了将近两小时才有成绩,很能理解很多大佬们五连WA感到愤怒的原因。

总体而言本次比赛初赛和复赛阶段的收获比较有限,最大的宝藏就是认识了一群优秀的同学,大家一起交流吹水十分快乐,感谢感谢!


参考资料:

1.数据生成.github.com/byl0561/HWco

2.测试数据.github.com/liusen1006/2

3.ddd的热身赛代码/初赛数据集分析.github.com/justarandoms

4.解读幂律分布与无标度网络.mp.weixin.qq.com/s?

5.无标度网络生成与可视化.networkx.github.io/docu

编辑于 2020-06-01 15:15