UVA 1048 - Low Cost Air Travel
题意:给定一些联票,在给定一些行程,要求这些行程的最小代价
思路:最短路,一张联票对应几个城市就拆成多少条边,结点表示的是当前完成形成i,在城市j的状态,这样去进行最短路,注意这题有坑点,就是城市编号可能很大,所以进行各种hash
代码:
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <map>
using namespace std;
const int MAXNODE = 50005;
const int MAXEDGE = 1000005;
typedef int Type;
const Type INF = 0x3f3f3f3f;
struct Edge {
int u, v, id;
Type dist;
Edge() {}
Edge(int u, int v, Type dist, int id) {
this->u = u;
this->v = v;
this->dist = dist;
this->id = id;
}
};
struct HeapNode {
Type d;
int u;
HeapNode() {}
HeapNode(Type d, int u) {
this->d = d;
this->u = u;
}
bool operator < (const HeapNode& c) const {
return d > c.d;
}
};
struct Dijkstra {
int n, m;
Edge edges[MAXEDGE];
int first[MAXNODE];
int next[MAXEDGE];
bool done[MAXNODE];
Type d[MAXNODE];
int p[MAXNODE];
void init(int n) {
this->n = n;
memset(first, -1, sizeof(first));
m = 0;
}
void add_Edge(int u, int v, Type dist, int id) {
edges[m] = Edge(u, v, dist, id);
next[m] = first[u];
first[u] = m++;
}
void print(int e) {//shun xu
if (p[e] == -1)
return;
print(edges[p[e]].u);
printf(" %d", edges[p[e]].id);
}
void dijkstra(int s) {
priority_queue<HeapNode> Q;
for (int i = 0; i < n; i++) d[i] = INF;
d[s] = 0;
p[s] = -1;
memset(done, false, sizeof(done));
Q.push(HeapNode(0, s));
while (!Q.empty()) {
HeapNode x = Q.top(); Q.pop();
int u = x.u;
if (done[u]) continue;
done[u] = true;
for (int i = first[u]; i != -1; i = next[i]) {
Edge& e = edges[i];
if (d[e.v] > d[u] + e.dist) {
d[e.v] = d[u] + e.dist;
p[e.v] = i;
Q.push(HeapNode(d[e.v], e.v));
}
}
}
}
} gao;
const int N = 25;
int n;
struct Ticket {
int val, hn, h[N];
} ti[N], tour;
int id[15][5005];
map<int, int> hash;
int cn;
int get2(int city) {
if (!hash.count(city)) hash[city] = cn++;
return hash[city];
}
int get(int num, int city) {
int tmp = get2(city);
if (id[num][tmp] == -1) id[num][tmp] = gao.n++;
return id[num][tmp];
}
void solve() {
cn = 0;
hash.clear();
gao.init(0);
memset(id, -1, sizeof(id));
scanf("%d", &tour.hn);
for (int i = 1; i <= tour.hn; i++)
scanf("%d", &tour.h[i]);
for (int i = 0; i < n; i++) {
for (int j = 0; j < tour.hn; j++) {
int u = j;
for (int k = 0; k < ti[i].hn; k++) {
if (ti[i].h[k] == tour.h[u + 1])
u++;
// printf("%d %d %d %d %d\n", j, ti[i].h[0], u, ti[i].h[k], ti[i].val);
gao.add_Edge(get(j, ti[i].h[0]), get(u, ti[i].h[k]), ti[i].val, i + 1);
if (u == tour.hn) break;
}
}
}
//printf("%d %d %d\n", tour.h[1], tour.hn, tour.h[tour.hn]);
gao.dijkstra(get(0, tour.h[1]));
printf("Cost = %d\n", gao.d[get(tour.hn, tour.h[tour.hn])]);
printf(" Tickets used:");
gao.print(get(tour.hn, tour.h[tour.hn]));
printf("\n");
}
int main() {
int cas = 0;
while (~scanf("%d", &n) && n) {
cas++;
for (int i = 0; i < n; i++) {
scanf("%d", &ti[i].val);
scanf("%d", &ti[i].hn);
for (int j = 0; j < ti[i].hn; j++)
scanf("%d", &ti[i].h[j]);
}
int q;
scanf("%d", &q);
for (int i = 1; i <= q; i++) {
printf("Case %d, Trip %d: ", cas, i);
solve();
}
}
return 0;
}