把当前国家与已学文化集合共同作为 Dijkstra 状态,并用集合包含关系做支配剪枝。
OJ: luogu
题目 ID: P1078
难度:提高+/省选-
标签:状态最短路Dijkstra支配剪枝python
日期: 2026-07-16 20:10
题意
路径上不能重复学习文化,也不能进入排斥任一已学文化的国家,求起终点最短路。原题被官方标为不保证多项式可解的错题。
思路
能否继续走取决于完整历史文化集合,不能只记录国家。状态为 (node, learned_mask),在其上运行 Dijkstra;Python 整数可直接容纳 100 位文化集合。
同一节点若已有状态文化集合是当前集合的子集,且距离不大于当前距离,那么它限制更少、代价更低,当前状态被支配。插入新状态时也删除被它支配的旧状态,缓解指数状态增长。
进入邻国前检查文化是否重复,以及邻国文化的排斥掩码是否与已学集合相交。
Python 知识
- 任意精度整数让
1 << culture可直接表示 100 种文化。 heapq处理非负边权状态最短路。- 列表推导式重建当前节点的非支配状态集合。
- 元组成员测试用于跳过已被删除的堆中旧状态。
代码
python
import heapq
import sys
data = iter(map(int, sys.stdin.buffer.read().split()))
n, culture_count, edge_count, start, target = (next(data), next(data), next(data),
next(data) - 1, next(data) - 1)
culture = [next(data) - 1 for _ in range(n)]
rejected = [0] * culture_count
for i in range(culture_count):
for j in range(culture_count):
if next(data):
rejected[i] |= 1 << j
graph = [[] for _ in range(n)]
for _ in range(edge_count):
u, v, weight = next(data) - 1, next(data) - 1, next(data)
graph[u].append((v, weight))
graph[v].append((u, weight))
best = [[] for _ in range(n)]
def add_state(node, mask, distance):
if any(old_distance <= distance and old_mask & mask == old_mask
for old_mask, old_distance in best[node]):
return False
best[node] = [(old_mask, old_distance) for old_mask, old_distance in best[node]
if not (distance <= old_distance and mask & old_mask == mask)]
best[node].append((mask, distance))
return True
start_mask = 1 << culture[start]
add_state(start, start_mask, 0)
heap = [(0, start, start_mask)]
answer = -1
while heap:
distance, node, mask = heapq.heappop(heap)
if (mask, distance) not in best[node]:
continue
if node == target:
answer = distance
break
for neighbor, weight in graph[node]:
next_culture = culture[neighbor]
bit = 1 << next_culture
if mask & bit or rejected[next_culture] & mask:
continue
next_mask = mask | bit
next_distance = distance + weight
if add_state(neighbor, next_mask, next_distance):
heapq.heappush(heap, (next_distance, neighbor, next_mask))
print(answer)复杂度
理论状态数可达
总结
正文不应伪称这题存在普通最短路多项式解;历史集合必须进入状态,官方数据性质才让剪枝搜索可运行。