POJ3411-Paid Roads

52 篇文章 0 订阅
16 篇文章 0 订阅

Paid Roads
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 7490 Accepted: 2755

Description

A network of m roads connects N cities (numbered from 1 to N). There may be more than one road connecting one city with another. Some of the roads are paid. There are two ways to pay for travel on a paid road i from city ai to city bi:

  • in advance, in a city ci (which may or may not be the same as ai);
  • after the travel, in the city bi.

The payment is Pi in the first case and Ri in the second case.

Write a program to find a minimal-cost route from the city 1 to the city N.

Input

The first line of the input contains the values of N and m. Each of the following m lines describes one road by specifying the values of aibiciPiRi (1 ≤ ≤ m). Adjacent values on the same line are separated by one or more spaces. All values are integers, 1 ≤ m, N ≤ 10, 0 ≤ Pi , Ri ≤ 100, Pi ≤ Ri (1 ≤ ≤ m).

Output

The first and only line of the file must contain the minimal possible cost of a trip from the city 1 to the city N. If the trip is not possible for any reason, the line must contain the word ‘impossible’.

Sample Input

4 5
1 2 1 10 10
2 3 1 30 50
3 4 3 80 80
2 1 2 10 10
1 3 2 10 50

Sample Output

110

Source

Northeastern Europe 2002, Western Subregion


题意:有n座城市和m条路。现在要从城市1到城市n。有些路是要收费的,从a城市到b城市,如果之前到过c城市,那么只要付P的钱,如果没有去过就付R的钱,问到n号城市要花的最少的钱

解题思路:就是一个最短路,多了一个预交费的C,所以在遍历的时候多了一维状态,这个维度储存当前走过的城市集合。在Dijkstra的时候,如果走过了C那么就花费P,否则花费R


#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <set>

using namespace std;

#define LL long long
const int INF = 0x3f3f3f3f;

int n, m;
int s[15], nt[15], c[15], e[15], p[15], r[15];
int dis[15][1<<12];

struct node
{
	int id, x, dis;
	friend bool operator <(node a, node b)
	{
		return a.dis > b.dis;
	}
}pre,nt1;

void Dijkstra()
{
	priority_queue<node>q;
	memset(dis, INF, sizeof dis);
	dis[1][0] = 0;
	pre.id = 1, pre.dis = 0, pre.x = 0;
	q.push(pre);
	while (!q.empty())
	{
		pre = q.top();
		q.pop();
		for (int i = s[pre.id]; ~i; i = nt[i])
		{
			int ee = e[i];
			int k = pre.x&(1 << c[i]) ? pre.dis + p[i] : pre.dis + r[i];
			int kk = pre.x | (1 << pre.id);
			if (k < dis[ee][kk])
			{
				dis[ee][kk] = k;
				nt1.id = ee, nt1.x = pre.x | (1 << pre.id), nt1.dis = k;
				q.push(nt1);
			}
		}
	}
	int mi = INF;
	for (int i = 0; i < (1 << (n + 1)); i++) mi = min(mi, dis[n][i]);
	if (mi == INF) printf("impossible\n");
	else printf("%d\n", mi);
}

int main()
{
	while (~scanf("%d%d", &n, &m))
	{
		memset(s, -1, sizeof s);
		int u, v, cc, pp, rr,cnt=1;
		for (int i = 1; i <= m; i++)
		{
			scanf("%d%d%d%d%d", &u, &v, &cc, &pp, &rr);
			nt[cnt] = s[u], s[u] = cnt, e[cnt] = v, c[cnt] = cc, p[cnt] = pp, r[cnt++] = rr;
		}
		Dijkstra();
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值