「こんなきれいな星も、やっぱりここまで来てから、見れたのだと思うから。だから・・もっと遠くへ・・」

关于POJ3165这道纠结的题目……

原题地址 http://poj.org/problem?id=3165

大概意思就是一条直线上有N个点(N<=1000),第i个点到第i+1个点之间有一条有向边(1<=i<N)……另外还有M条边(M<=10000),第i条边是从Si到Ei的有向边(Si<=Ei)……

然后有3个人,每个人有各自的起点和终点…… 他们可以各自顺着边前行,走一条边的价格是1元,也可以组队前行,不管有多少个人,一起走过一条边总共只要1元…… 问你各人都到达目的地最少的总钱数……

这道题目其实和POJ3123基本差不多……

算法也差不多…… 只是POJ3123里面的边是无向边,而这里是有向边……

大概就是把每个人是否访问到了他的起点/终点表示出来,就是一个6位二进制串…… 这样dp状态dp[i,mask]表示当前在i,访问状态是mask……

第一种转移: 往前顺着某条边走过去。如果mask是配对的(没有出现某个人访问了起点却没有访问他的终点的情况),那么这只是虚拟的走,不用代价,否则代价为1.

第二种转移: 某个人脱离队伍,直接独自走向他的终点(要求:这个人访问了起点,但没访问他的终点)…… 这个可以先用O(NM)时间把任意两个点之间距离预处理出来……

第三种转移: 某个人加入当前的队伍,从起点走向当前点(要求:这个人没有访问过起点)…… 同样,因为距离预处理出来了,也是O(1)的……

第四种转移: 合并两个当前节点相同的状态…… 要求两个子状态的mask都是配对的…… 代价就是两个状态代价的和……

于是用类似spfa的方法BFS一遍就行了…… 于是总时间复杂度O(NM+4096N)

但这道题很纠结……因为这题数据(曾经)是错的…… 标程木有考虑到第四种转移(我写第四种转移的版本WA了,但去掉第四种转移反而AC)…… 但不考虑第四种转移显然是有问题的,例如这组数据

5 1
1 5
1 1 2
5 5 4

不考虑第四种转移就会输出4…… 但实际答案显然是3……

后来和dhu_try讨论了一下,try找管理员要了数据和标程,发现标程确实错了…… 数据也有一组正好要用到第四种转移,于是数据也错了…… 于是try让我拍了10组要用到第四组转移的数据交给管理员一起rejudge……

但貌似管理员直接把原来的大数据给下掉了,换成了我的10组小数据…… 于是冒出一大堆AC…… 朴素也能过了……>__< (UPDATE:现在大数据已经重新放上去了)

当然,虽然已经和3个程序对拍过,但我上面的想法可能依然有问题…… 欢迎神犇来cha……

提供代码供神犇找bug…… 代码在 https://ideone.com/e9c3z ,里面附带的10组数据就是我提供给POJ的数据,都是需要用到第四种转移的。

如果有神犇找到新的bug或者问题请留言……谢谢……