题目链接
http://acm.hust.edu.cn/vjudge/problem/22966
思路
因为商业线只能够选择一次,只需要枚举这K条商业线,设每次选中的一条商业A->B的起点为A,终点为B,则起点到A和B到终点必然选择的是经济线
因此只需要对起点和终点分别做一次dijkstra,设起点到A的时间为f(a), B到终点的时间为g(b),则T = f(a) + g(b) + T(a, b)
细节
- 注意路径输出的格式以及换行
- 商业线也为双向路径
代码
#include <iostream>
#include <cstring>
#include <stack>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <sstream>
#include <iomanip>
#include <fstream>
#include <cstdio>
#include <cstdlib>
#include <climits>
#include <deque>
#include <bitset>
#include <algorithm>
using namespace std;
#define PI acos(-1.0)
#define LL long long
#define PII pair<int, int>
#define PLL pair<LL, LL>
#define mp make_pair
#define IN freopen("in.txt", "r", stdin)
#define OUT freopen("out.txt", "wb", stdout)
#define scan(x) scanf("%d", &x)
#define scan2(x, y) scanf("%d%d", &x, &y)
#define scan3(x, y, z) scanf("%d%d%d", &x, &y, &z)
#define sqr(x) (x) * (x)
#define pr(x) cout << #x << " = " << x << endl
#define lc o << 1
#define rc o << 1 | 1
#define pl() cout << endl
const int maxn = 505;
const int INF = 0x3e3e3e3e;
struct Edge {
int from, to, dist;
Edge(int a, int b, int c) : from(a), to(b), dist(c) {
}
};
struct cmp {
bool operator() (PII x, PII y) {
return y.second < x.second;
}
};
vector<Edge> edges;
vector<int> G[maxn];
vector<Edge> quick;
int n, m, k, S, E, tot = 0;
void init() {
for (int i = 0; i <= n; i++) G[i].clear();
quick.clear();
edges.clear();
tot = 0;
}
void addedge(int u, int v, int w) {
edges.push_back(Edge(u, v, w));
int m = edges.size();
G[u].push_back(m - 1);
}
void dijkstra(int s, int *d, int *p) {
bool vis[maxn];
memset(vis, 0, sizeof(vis));
fill(d, d + n + 1, INF);
d[s] = 0;
p[s] = -1;
priority_queue<PII, vector<PII>, cmp> Q;
Q.push(mp(s, 0));
while (!Q.empty()) {
PII x = Q.top(); Q.pop();
int u = x.first;
if (vis[u]) continue;
vis[u] = 1;
for (int i = 0; i < G[u].size(); i++) {
Edge &e = edges[G[u][i]];
int v = e.to;
if (d[v] > d[u] + e.dist) {
d[v] = d[u] + e.dist;
Q.push(mp(v, d[v]));
p[v] = u;
}
}
}
}
void print_path(int x, int *p) {
if (x == -1) return;
print_path(p[x], p);
if (!tot) cout << x;
else cout << ' ' << x;
tot++;
}
void print_path2(int x, int *p) {
if (x == -1) return;
if (!tot) cout << x;
else cout << ' ' << x;
tot++;
print_path2(p[x], p);
}
int main() {
int kase = 0;
while (~scan3(n, S, E)) {
scan(m);
init();
for (int i = 0; i < m; i++) {
int x, y, z;
scan3(x, y, z);
addedge(x, y, z);
addedge(y, x, z);
}
scan(k);
for (int i = 0; i < k; i++) {
int x, y, z;
scan3(x, y, z);
quick.push_back(Edge(x, y, z));
quick.push_back(Edge(y, x, z));
}
int d1[maxn], d2[maxn], p1[maxn], p2[maxn];
dijkstra(S, d1, p1);
dijkstra(E, d2, p2);
int _s = quick.size();
int f[maxn], res = d1[E], sta = 1, sed = 1;
for (int i = 0; i < _s; i++) {
Edge e = quick[i];
f[i] = quick[i].dist;
f[i] += d1[quick[i].from];
f[i] += d2[quick[i].to];
if (f[i] < res) {
res = f[i];
sta = quick[i].from;
sed = quick[i].to;
}
}
if (kase) pl();
kase++;
if (res != d1[E]) {
print_path(sta, p1);
print_path2(sed, p2);
pl();
printf("%d\n%d\n", sta, res);
} else {
print_path(E, p1);
pl();
puts("Ticket Not Used");
printf("%d\n", res);
}
}
return 0;
}