////题目描述////
Bug魔王派出了N种怪物来入侵亚特兰蒂斯,聪明的亚特兰蒂斯国王Cubic预先得知了Bug魔王的阴谋,并了解到每种怪物都对应一种剑术和一种法术,这种怪物可以被对应的剑术打败也可以被对应的法术打败。不同的怪物可能对应不同的剑术和法术,而一种剑术或法术可以击败多种怪物。只要Cubic得到某怪物的信息,他就可以知道对应的剑术和法术,不会只知其一。
令国王感到欣慰的是亚特兰蒂斯最优秀的剑术师Xixi和最优秀的法术师Haha决定挺身而出,保卫国家。但问题是他们并不会这些特定的剑术和法术,必须抓紧时间学习。由于学习新剑术或新法术需要闭关,为防止Bug魔王偷袭,必须留下一个负责看守,因此两人不能同时学习。学习一种剑术或一种法术的时间都是1。现在的问题是他们到底需要学习那些剑术和法术,才能在最短的时间内拥有打败所有怪物的能力呢?
聪明的Cubic国王也发愁了,于是他决定聘请更聪明的你为亚特兰蒂斯的顶级技术顾问(相当于副科级),来帮他解决这个问题,全靠你了。
输入格式:输入有多组数据。对于每组数据:
第1行是3个整数 P(1<=P<=10000),N(0<=N<=500)和M(0<=M<=500),分别表示怪物、剑术和法术的种数。接下来P行,每行一个字符串,分别表示P种怪物的名字。
再接下来N+M行,表示一种剑术或法术的信息。前N行是剑术,后M行是法术。对于每一行,首先是一个字符串,表示剑术或法术的名字;然后是一个非负整数K(K<=P),表示这种剑术或法术可以击败的怪物种数;然后就是K个字符串,表示K种怪物的名字。这些怪物都在上面的P种怪物之内。
所有的字符串都只由字母和连字符(-)组成,长度不超过15。两个字符串以空格隔开。所有字符串都不相同。
最后1行有3个-1,表示输入结束。
输出格式:对于每组数据,输出一个整数,表示要拥有打败所有怪物的能力所需要的最少时间。如果无法打败所有的怪物,输出“Poor Atlantis!”。
Savior.in
5 3 2
ant
rocking
kinfkong
savior
magicpig
AlongNineSword 2 ant kinfkong
HuaShanSword 2 rocking savior
TaijiSword 1 magicpig
Wind_walk 3 ant rocking magicpig
Blade-storm 2 kinfkong savior
-1 -1 -1
Savior.out
2
一开始想的是建两幅图,分别是剑和怪,法术和怪的匹配,然后再跑两遍最大流,至少要全部覆盖,然后找两个之中最小的输出。
然而怪是1~10000个,节点数就非常大了。
因此引入概念:最小覆盖点集。我们可以将剑术放一边,法术放另一边,两边有共同的怪即为边,求最少的点,使得所有的边都覆盖。而最小覆盖点集等于最大匹配,只需求一边最大匹配即可。
然而,此题还涉及一个字符串hash。需要把怪,剑,法的名称转化为一定范围内的数值进行操作。由于怪物数据较大,冲突的情况很多。因此考虑怪物使用不用的hash算法。虽然十分暴力的挨个尝试了素数,又用了300多mb内存,才终于过了最后两个点。
只能算80分了
1 |
|
5.29更新
感谢FLX菊苣提点,更新了C++版本,使用了STL的map,效率惊人……%%%%%
1 |
|