UVA 11374 Air Express

這道題其實就是這個意思:給你m條路,可以隨便走;再給你K條路,這K條路一共只能走一次(可以不走),問從A到B最快要多久.

        這道題,其實是道水題,可以參考劉汝佳的藍書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("\n");
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("\n%d\n",x);
     }
     else {
      x=last[at][1];
      printf("%d",at);      
      while(x!=-1){
      printf(" %d",x);
      x=last[x][1];

printf("\nTicket Not Used\n");
}
    printf("%d\n",ans);
    for(int i=1;i<=n;i++)G[i].clear();
    edges.clear();
}
    return 0;
}
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章