• 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

  • 相关阅读:
    [日常摸鱼]一些素数筛法(暴力筛/埃氏筛/欧拉筛)与复杂度证明
    [日常摸鱼]一些博弈题
    [日常摸鱼]博弈论入门/经典模型/SG函数
    [日常摸鱼]整点正多边形,HDU6055,Pick公式,证明
    [日常摸鱼]一些DP题(2)各种背包——01背包/二维背包/背包前K优解
    [学习笔记]程设作业的一些YY,高精度除法/FFT/Karastuba/牛顿迭代
    [比赛记录]2020-2021 Summer Petrozavodsk Camp, Day 6: Korean Contest
    [日常摸鱼]一些DP题(1)
    [日常摸鱼]poj3179-Corral the Cows——离散化+二维前缀和/KD-Tree
    《HDU-1028》
  • 原文地址:https://www.cnblogs.com/00isok/p/10076006.html
Copyright © 2020-2023  润新知