"""
题目:设有n个城市组成的交通图,一个售货员从住地城市q出发,到其它城市各一次去推销货物,最后回到住地城市。
要求:假定两个城市a,b 从a到b的路程花费w_ab是已知的,问应该怎样选择一条花费最少的路线?
输入格式:
第一行n m q,n和m两个整数分别表示城市数n以及城市之间的单向路数量m,q表示住地城市(出发城市)
之后m行 a b w分别表示从城市a到城市b的单向路程的花费w_ab。
输出格式:
第一行输出最小花费是D,D表示计算得到的最小花费。
第二行输出最小花费共有N种方案,分别是:,N表示最小花费方案的种类,
接下来N行输出每种方案的前往顺序,以字典序排序输出,中间以空格分隔。
输入样例:
3 6 A
A B 12
A C 4
B C 5
B A 8
C B 7
C A 2
输出样例:
最小花费是19
最小花费共有2种方案,分别是:
A B C
A C B
"""
from itertools import permutations
import sys
def tsp(n, m, q, edges):
# 将城市名称转换为索引
city_to_index = {chr(ord('A') + i): i for i in range(n)}
index_to_city = {i: chr(ord('A') + i) for i in range(n)}
if q not in city_to_index:
raise ValueError(f"住地城市 {q} 不存在于城市列表中。")
q = city_to_index[q]
# 初始化距离矩阵,INF 表示两城市间无直接路径
INF = sys.maxsize
dist = [[INF] * n for _ in range(n)]
for i in range(n):
dist[i][i] = 0
for a, b, w in edges:
if a not in city_to_index or b not in city_to_index:
raise ValueError(f"城市 {a} 或 {b} 不存在于城市列表中。")
dist[city_to_index[a]][city_to_index[b]] = w
# 动态规划表
dp = [[INF] * n for _ in range(1 << n)]
dp[1 << q][q] = 0
# 遍历所有状态
for mask in range(1 << n):
for i in range(n):
if mask & (1 << i):
for j in range(n):
if not mask & (1 << j):
dp[mask | (1 << j)][j] = min(
dp[mask | (1 << j)][j], dp[mask][i] + dist[i][j])
# 寻找最小花费
min_cost = INF
for i in range(n):
if i != q:
min_cost = min(min_cost, dp[(1 << n) - 1][i] + dist[i][q])
# 找到所有最小花费的路径
def find_paths(mask, i):
if mask == (1 << q):
return [[index_to_city[i]]]
paths = []
for j in range(n):
if mask & (1 << j) and dp[mask][i] == dp[mask ^ (1 << i)][j] + dist[j][i]:
for path in find_paths(mask ^ (1 << i), j):
paths.append(path + [index_to_city[i]])
return paths
result_paths = []
for i in range(n):
if i != q and dp[(1 << n) - 1][i] + dist[i][q] == min_cost:
for path in find_paths((1 << n) - 1, i):
result_paths.append(path)
result_paths = sorted(result_paths)
return min_cost, result_paths
# 输入处理
n, m, q = input().split()
n = int(n)
m = int(m)
edges = []
for _ in range(m):
a, b, w = input().split()
w = int(w)
edges.append((a, b, w))
min_cost, result_paths = tsp(n, m, q, edges)
# 输出结果
print(f"最小花费是{min_cost}")
print(f"最小花费共有{len(result_paths)}种方案,分别是:")
for path in result_paths:
print(" ".join(path))