这道题,其实是道水题,可以参考刘汝佳的蓝书P330。我们从A为起点,做一次单源最短路径,把点X离A的距离记为
dis[x][0],然后再以B为起点,做一次单源最短路径,把点X离B的距离记为dis[x][1]。我们设这K条路中任意一条路为x-y,长度为z且经过这条路,则A到B的路径只能是A-x-y-B或A-y-x-B。那么这个长度就是dis[x][0]+dis[y][1]+z或dis[x][1]+dis[y][0]+z,把最短的一个的x和y,最后再与直接从A到B(不走这K条路中的任意一条)对比一下,就算出了第二个答案和第三个答案了.统计路径,其实也很简单,具体参考代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
#include<cmath>
using namespace std;
const int inf=0x3f3f3f3f;
int n,m,at,to;
int dis[1005][2],vis[1005];
struct node{
int to;
int dis;
bool operator <(const node &rhs)const{
return dis>rhs.dis;
}
}xs;
struct Edge{
int from;
int to;
int len;
};
vector<Edge>edges;
vector<int>G[1005];
priority_queue<node>p;
int len;
void addedge(int x,int y,int z){
edges.push_back((Edge){x,y,z});
G[x].push_back(len);
len++;
}
int last[1005][2];
void dijkstra(int k,int root){
int u;
memset(vis,0,sizeof(vis));
dis[root][k]=0;
p.push((node){root,0});
while(p.size()){
xs=p.top();p.pop();
u=xs.to;
if(vis[u])continue;
vis[u]=1;
for(int i=0;i<G[u].size();i++){
Edge &e=edges[G[u][i]];
if(dis[u][k]+e.len<dis[e.to][k]){
dis[e.to][k]=dis[u][k]+e.len;
last[e.to][k]=u;//记录它的上一个点
p.push((node){e.to,dis[e.to][k]});
}
}
}
}
int x,y,z,tmp,cases;
int where1,where2;
stack<int>out;
int main(){
while(scanf("%d%d%d%d",&n,&at,&to,&m)!=EOF){
if(cases)printf("
");
cases++;
len=0;
for(int i=1;i<=m;i++){
scanf("%d%d%d",&x,&y,&z);
addedge(x,y,z);
addedge(y,x,z);
}
memset(last,0,sizeof(last));
memset(dis,inf,sizeof(dis));
last[at][0]=last[to][1]=-1;
where1=where2=0;
int ans=inf;
dijkstra(0,at);
dijkstra(1,to);
scanf("%d",&m);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&x,&y,&z);
tmp=dis[x][0]+dis[y][1]+z;
if(tmp<ans){
ans=tmp;
where1=x;where2=y;
}
tmp=dis[y][0]+dis[x][1]+z;
if(tmp<ans){
ans=tmp;
where1=y;where2=x;
}
}
if(ans>dis[at][1]){
ans=dis[at][1];
where1=where2=0;
}
if(where1&&where2){
x=where1;
while(where1!=-1){
out.push(where1);
where1=last[where1][0];
}
while(out.size()){
printf("%d ",out.top());
out.pop();
}
printf("%d",where2);
where2=last[where2][1];
while(where2!=-1){
printf(" %d",where2);
where2=last[where2][1];
}
printf("
%d
",x);
}
else {
x=last[at][1];
printf("%d",at);
while(x!=-1){
printf(" %d",x);
x=last[x][1];
}
printf("
Ticket Not Used
");
}
printf("%d
",ans);
for(int i=1;i<=n;i++)G[i].clear();
edges.clear();
}
return 0;
}