POJ 3411 Paid Roads 百炼 3148:样例分析+详细题解

题目链接:poj百炼

题目大意

有 n 座城市和 m 条单向道路(两个城市之间可能有多条单向道路)。每次通过一条道路都要支付过路费(多次经过需要多次支付过路费),对于边 (ai,bi),过路费有两种支付方式:

  1. 如果之前到达过城市 ci,那么只需要支付 Pi块钱。(ci可能等于 ai)。
  2. 直接支付 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 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值