题意
有廉价线路和普通线路,只有一次乘坐普通线路的机会,问从S到E花费最少的线路。并输出路径。
题解
由于只有一次机会,因此可以直接枚举乘坐的普通线路。针对每次选择,两遍SPFA(枚举正向和反向)。至于输出路径,只需要记录每个点的最短路径上一个点就可以了。输出的时候递归输出就可以了。
代码
#include<bits/stdc++.h>
#define LL long long
#define UP(i,l,h) for(int i=l;i<h;i++)
#define DOWN(i,h,l) for(int i=h-1;i>=l;i--)
#define W(t) while(t)
#define MEM(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MAXN 510
#define COUT(x) cout<<x<<endl
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
struct Node{
int to,w;
Node(int to,int w):to(to),w(w){}
bool operator == (Node b) const{
return to==b.to&&w==b.w;
}
};
vector<Node> vc[MAXN];
bool vis[MAXN];
int dis[MAXN],f[MAXN],ansf[MAXN];
int n,s,e;
void spfa(int x){
MEM(vis,false);
queue<int> q;
q.push(x);
dis[x]=0;
vis[x]=true;
W(!q.empty()){
int r=q.front();
q.pop();
vis[r]=false;
for(Node y:vc[r]){
if(y.w+dis[r]<dis[y.to]){
f[y.to]=r;
dis[y.to]=y.w+dis[r];
if(!vis[y.to]){
q.push(y.to);
vis[y.to]=true;
}
}
}
}
}
void print(int now){
if(now!=s){
print(ansf[now]);
if(now==e) printf("%d\n",now);
else printf("%d ",now);
}else printf("%d ",now);
}
int main(){
// freopen("e://in.txt","r",stdin);
// freopen("e://ou.txt","w",stdout);
bool good=false;
W(~scanf("%d%d%d",&n,&s,&e)){
if(good) puts("");
else good=true;
MEM(vc,0);
MEM(f,-1);
MEM(dis,INF);
int use=-1;
int m,k;
scanf("%d",&m);
int x,y,w;
UP(i,0,m){
scanf("%d%d%d",&x,&y,&w);
vc[x].push_back(Node(y,w));
vc[y].push_back(Node(x,w));
// COUT(w);
}
scanf("%d",&k);
spfa(s);
int ans=dis[e];
// COUT(ans);
memcpy(ansf,f,sizeof(f));
UP(i,0,k){
MEM(f,-1);
MEM(dis,INF);
scanf("%d%d%d",&x,&y,&w);
vc[x].push_back(Node(y,w));
spfa(s);
auto it=find(vc[x].begin(),vc[x].end(),Node(y,w));
vc[x].erase(it);
if(dis[e]<ans){
use=x;
ans=dis[e];
memcpy(ansf,f,sizeof(f));
}
// COUT("dis"<<dis[e]);
MEM(f,-1);
MEM(dis,INF);
vc[y].push_back(Node(x,w));
spfa(s);
it=find(vc[y].begin(),vc[y].end(),Node(x,w));
vc[y].erase(it);
if(dis[e]<ans){
use=y;
ans=dis[e];
memcpy(ansf,f,sizeof(f));
}
// COUT("dis"<<dis[e]);
}
print(e);
if(use==-1) puts("Ticket Not Used");
else printf("%d\n",use);
printf("%d\n",ans);
}
}