题意
在一张图中有两种路线,一种是经济线,一种是商业线,经济线可以随便走,但是商业线只能走一次。现在问从起点到终点的最短路是什么。
题解
预处理起点和终点最短路。
设起点为S,终点为E。
枚举每一条商业线(u,v),现在需要快速知道S->u的最短路径,v->E的最短路径,这样就可以得出选这条商业线的最短路。解决的办法是预处理,以起点和终点分别开始跑一遍最短路,得出数组d1[i]
,d2[j]
。那么选择商业线(u,v,w)的最短路径就是d1[u]+w+d2[v]
。
枚举每一条商业线取最小即可。
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 500+5;
const int INF = 0x3f3f3f3f;
#define to second
#define co first
typedef pair<int, int> pii;
vector<pii> G[maxn];
int n,S,E;
int d1[maxn];
int d2[maxn];
int path[maxn];
void solve(int s, int d[]) {
memset(path,0, sizeof path);
for(int i = 0; i <= n; ++i)
d[i] = INF;
d[s] = 0;
priority_queue<pii,vector<pii>, greater<pii> > que;
que.push(pii(d[s],s));
while(!que.empty()) {
pii u = que.top();
que.pop();
if(d[u.second] < u.first)
continue;
int x = u.second;
// cout << x << endl;
for(int i = 0; i < G[x].size(); ++i) {
pii &e = G[x][i];
if(d[e.to] > d[x]+e.co) {
d[e.to] = d[x]+e.co;
que.push(pii(d[e.to],e.to));
path[e.to] = x;
}
}
}
}
void find() {
queue<pii> que;
que.push(pii(d1[S],S));
while(!que.empty()) {
pii u = que.front();
que.pop();
int x = u.second;
// cout << x << endl;
for(int i = 0; i < G[x].size(); ++i) {
pii &e = G[x][i];
if(d1[e.to] == d1[x]+e.co) {
d1[e.to] = d1[x]+e.co;
que.push(pii(d1[e.to],e.to));
path[e.to] = x;
}
}
}
}
void add(int u,int v,int c) {
G[u].push_back(pii(c,v));
}
int main() {
// freopen("in.txt","r",stdin);
int kas = 0;
while(~scanf("%d", &n)) {
if(kas)
puts("");
kas++;
for(int i = 0; i <= n; ++i)
G[i].clear();
scanf("%d%d", &S,&E);
int m;
scanf("%d", &m);
for(int i = 0; i < m; ++i) {
int u,v,c;
scanf("%d%d%d",&u,&v,&c);
add(u,v,c);add(v,u,c);
}
solve(S,d1);
solve(E,d2);
// for(int i = 1; i <= n; ++i)
// cout << d1[i] << " " ;
// cout << endl;
int k;
scanf("%d", &k);
int _dis = d1[E];
int au = -1,av = -1,ac = -1;
for(int i = 0; i < k; ++i) {
int u,v,c;
scanf("%d%d%d",&u,&v,&c);
for(int j = 0; j < 2; ++j) {
int tmp = d1[u]+d2[v]+c;
if(tmp < _dis) {
_dis = tmp;
au = u, av = v, ac = c;
}
swap(u,v);
}
}
if(au != -1) {
add(au,av,ac);
add(av,au,ac);
}
solve(S,d1);
stack<int> p;
int x = E;
while(x) {
p.push(x);
x = path[x];
}
while(!p.empty()) {
int u = p.top();
p.pop();
if(p.empty())
printf("%d\n", u);
else
printf("%d ", u);
}
if(au != -1)
printf("%d\n", au);
else
puts("Ticket Not Used");
printf("%d\n", _dis);
}
return 0;
}