1. 程式人生 > >HDU 1385 Minimum Transport Cost (輸出字典序最小路徑)【最短路】

HDU 1385 Minimum Transport Cost (輸出字典序最小路徑)【最短路】

<題目連結>

題目大意:
給你一張圖,有n個點,每個點都有需要繳的稅,兩個直接相連點之間的道路也有需要花費的費用。現在進行多次詢問,給定起點和終點,輸出給定起點和終點之間最少花費是多少,並且輸出最少花費所走的路徑,如果有多條路徑花費最少,則輸出字典序最小的那條。

解題分析:

輸出最短路的路徑問題,需要注意的是,題目要求輸出的最短路徑的字典序最小,所以我們在每次鬆弛的時候,都需要加上判斷。如果有多個點的最短路相同,則用DFS求出它們之前走過的路徑,並且進行比較,然後選字典序最小的那條。

 1 #include <cstdio>
 2 #include <iostream>
 3
#include <cstring> 4 #include <algorithm> 5 using namespace std; 6 7 #define clr(a,b) memset(a,b,sizeof(a)) 8 #define rep(i,s,t) for(int i=s;i<=t;i++) 9 #define INF 0x3f3f3f3f 10 const int M = 100+10; 11 int n,pos; 12 int path[M],mp[M][M],tax[M],vis[M],dis[M]; 13 char s1[110
],s2[110]; 14 void dfs(int cur,char *s){ //找到這個點之前記錄的路徑s 15 if(cur == -1)return; 16 dfs(path[cur],s); 17 s[pos++]=cur+'0'; 18 } 19 bool Compare(int re,int now) { 20 pos=0;dfs(re,s1);s1[pos] = '0'; //將起點到re的最短路徑儲存 21 pos=0;dfs(now,s2);s2[pos++]=re+'0';s2[pos]=0; //將起點到u的最短路徑儲存
22 if(strcmp(s1,s2)>0)return true; //比較兩個最短路之間的大小 23 return false; 24 } 25 void Dij(int st,int ed){ 26 rep(i,1,n){ 27 dis[i]=mp[st][i]+tax[i]; //將與st直接相連的點,邊權與點權相加,視為經過i號城市的代價 28 if(i==st)continue; 29 if(dis[i]<INF)path[i]=st; //初始化path 30 } 31 rep(i,1,n){ 32 int mn=INF,cur; 33 rep(j,1,n) if(dis[j] < mn && !vis[j]) { //找到每一輪的起始節點 34 mn=dis[j],cur=j; 35 }vis[cur]=1; 36 rep(k,1,n) if(mp[cur][k] < INF){ 37 if(dis[k]>dis[cur]+mp[cur][k]+tax[k]){ //進行鬆弛,並且記錄上一個節點 38 dis[k]=dis[cur]+mp[cur][k]+tax[k]; 39 path[k]=cur; 40 }else if(dis[k] == dis[cur]+mp[cur][k]+tax[k] && Compare(k,cur)){ 41 path[k]=cur; 42 }//若有多條最短路徑(最短距離相同的時候)進行字典序大小判斷,注意不能只比較一個節點,需要比較整個路徑 43 } 44 } 45 } 46 void show(int cur,int st){ 47 if(cur == st){ cout<<cur; return ;} 48 show(path[cur],st); 49 cout<<"-->"<<cur; 50 } 51 int main(){ 52 while(~scanf("%d",&n),n){ 53 rep(i,1,n) rep(j,1,n){ 54 scanf("%d",&mp[i][j]); 55 if(mp[i][j]==-1)mp[i][j]=INF; 56 } 57 rep(i,1,n)scanf("%d",&tax[i]); 58 int u,v;while(scanf("%d%d",&u,&v)){ 59 if(u==-1 && v==-1)break; 60 clr(vis,0);clr(path,-1); 61 Dij(u,v); 62 cout<<"From "<<u<<" to "<<v<<" :"<<endl<<"Path: "; 63 show(v,u);puts(""); //從終點開始,利用遞迴,將逆序儲存的路徑正序輸出 64 cout<<"Total cost : "<<dis[v]-tax[v]<<endl<<endl; //減去終點城市的城市稅 65 } 66 } 67 }

 

 

2018-12-06