题目大意
有 n 座城市和 m 条单向道路(两个城市之间可能有多条单向道路)。每次通过一条道路都要支付过路费(多次经过需要多次支付过路费),对于边 (ai,bi),过路费有两种支付方式:
- 如果之前到达过城市 ci,那么只需要支付 Pi块钱。(ci可能等于 ai)。
- 直接支付 Ri块钱。
问从 1 号城市到 n 号城市最少需要多少钱。
输入
第一行输入两个整数 n,m(1 ≤ n,m ≤ 10) 表示点数和边数。接下来 m 行每行五个整数 ai,bi,ci,Pi,Ri,描述了一条边。
输入数据保证 0 ≤ Pi ≤ Ri ≤ 100, 1 ≤ ai,bi,ci ≤ n.
输出
输出一行一个整数,表示最少的花费。如果不管怎么样都无法到达,输出impossible
大体思路
这道题与状压DP解TSP有异曲同工之妙。都是最短路径问题,因此我们不妨设一个数组dp[s][i]
:当前在点i
,已经经过了点集s
的最小花费,显然点集s
就是我们要压缩的对象。但是与TSP问题不同,我们可以可以经过某个点两次以上,因此不太适合迪杰斯特拉,使用SPFA即可。注意此时路径有两种花费,需要进行判断。spfa代码如下,
while (!q.empty()) {
int id = q.front(); q.pop(); vis[id] = 0;
for (unsigned i = 0; i < g[id].size(); i++) {
//遍历所有邻接点
int to = g[id][i].to, by = g[id][i].advance;
int c1 = g[id][i].cost1, c2 = g[id][i].cost2;
for (int k = 1; k < (1 << n); k++) {
//遍历所有状态
if (!(k&(1 << (id - 1)))) continue;//k状态连id点都不包含
int dist = ((1 << (by - 1))&k) ? c1 : c2;//经过了中间点就是cost2,否则就是正常花费
if (dist + dp[k][id] < dp[k | (1 << (to - 1))][to]) {
dp[k