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 ai, bi, ci, Pi, Ri (1 ≤ i ≤ 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 ≤ i ≤ 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
题意:有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;
}