hdu 1385 Minimum Transport Cost

点击打开链接hdu 1385

思路:最短路+SPFA+路径记录+路径字典序比较

分析:
1 题目要求的单源的最短路,所以可以选择任意一种单源最短路来求解
2 题目还要求在路径和相同情况下要字典序小的,那么就要在更新dis数组的时候进行更新路径,如果是dis[i]>tmp,那么直接更新;如果是dis[i] == tmp的情况下,那么就要求出star->i 和 star->x的路径进行比较,然后判断能否更新.

3 注意询问的时候可能问的是同一个点。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;

#define MAXN 110
#define INF 0xFFFFFFF

int n , star , end , pos;
int value[MAXN][MAXN];
int tmp_value[MAXN][MAXN];
int dis[MAXN];
int charge[MAXN];
int vis[MAXN];
int route[MAXN];
int father[MAXN];
int tmp_charge[MAXN];
queue<int>q;

/*初始化数组*/
void init(){
   for(int i = 1 ; i <= n ; i++){
      for(int j = 1 ; j <= n ; j++)
         value[i][j] = INF;
      value[i][i] = 0;
   }
}

/*dfs找路径*/
void dfs(int num , char *str){
     if(num == -1)
       return;
     dfs(father[num] , str);
     str[pos++] = num+'0';
}

void SPFA(int s){
   memset(vis , 0 , sizeof(vis));
   for(int i = 1 ; i <= n ; i++){
      dis[i] = INF;
      father[i] = -1;
   }
   vis[s] = 1;
   dis[s] = 0;
   q.push(s);
   while(!q.empty()){
       int x = q.front();
       q.pop();
       vis[x] = 0;
       for(int i = 1 ; i <= n ; i++){
          int tmp = dis[x] + tmp_value[x][i] + tmp_charge[x];
          /*dis[i]>tmp直接更新*/
          if(dis[i] > tmp){
             dis[i] = tmp;
             father[i] = x;
             if(!vis[i]){
                vis[i] = 1;
                q.push(i);
             }
          }
          /*dis[i] == tmp的时候求出路径*/
          else if(dis[i] == tmp && x != i && dis[i] != INF){        
             char ch1[MAXN] = {'\0'} , ch2[MAXN] = {'\0'};
             pos = 0;
             dfs(i , ch1);
             pos = 0;
             dfs(x , ch2);
             ch2[pos] = x+'0';/*这个地方注意就是x要加上去*/
             /*如果字典序小就要更新*/
             if(strcmp(ch1 , ch2) > 0){
                father[i] = x;
                if(!vis[i]){
                  vis[i] = 1;
                  q.push(i);
                }
             }
          }
       }
   }
}

int main(){
   int x , y , num , cnt , ans;
   while(scanf("%d" , &n) && n){
      init();
      /*输入边*/
      for(int i = 1 ; i <= n ; i++){
         for(int j = 1 ; j <= n ; j++){
            scanf("%d" , &num);  
            if(num != -1 && value[i][j] > num)
              value[i][j] = num;
         }
      }
      /*输入过路费*/
      for(int i = 1 ; i <= n ; i++)
         scanf("%d" , &charge[i]);
      /*询问*/
      while(1){
         scanf("%d%d" , &star , &end);
         if(star == -1 && end == -1)
           break;
         /*数组复制*/
         memcpy(tmp_charge , charge , sizeof(charge));
         memcpy(tmp_value , value , sizeof(value));
         tmp_charge[star] = tmp_charge[end] = 0;/*起点和终点的过路费为0*/
         
         SPFA(star);
         
         /*输出*/
         printf("From %d to %d :\n" , star , end);
         printf("Path: ");
         
         memset(route , 0 , sizeof(route));
         ans = dis[end];

         if(star != end){
            cnt = 0;
            x = end;
            while(1){
               y = father[x];
               route[cnt++] = y;
               if(y == star)
                 break;
               x = y;
            }
            for(int i = cnt-1 ; i >= 0 ; i--)
              printf("%d-->" , route[i]);
         }

         printf("%d\n" , end);
         printf("Total cost : %d\n\n" , ans);
      }
   }
   return 0;
}

2 floyd  ,由于floyd是每一次都用k去更新dis,所以我们只要在更新的同时更新path即可,由于k是从1-n的,那么这样最后的path肯定是字典序最小的。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

#define MAXN 110
#define INF 0xFFFFFFF

int n;
int value[MAXN][MAXN];
int charge[MAXN];
int path[MAXN][MAXN];

void init(){
   for(int i = 1 ; i <= n ; i++){
      for(int j = 1 ; j <= n ; j++){
         value[i][j] = INF;
         path[i][j] = j;
      }
      value[i][i] = 0;
   }
}

void floyd(){
    for(int k = 1 ; k <= n ; k++){
       for(int i = 1 ; i <= n ; i++){
          for(int j = 1 ; j <= n ; j++){
            int tmp = value[i][k]+value[k][j]+charge[k];
            if(value[i][j] > tmp){
              value[i][j] = tmp;
              path[i][j] = path[i][k];
            }
            else if(value[i][j] == tmp && path[i][j] > path[i][k])
              path[i][j] = path[i][k];
          }
       }
    }
}

int main(){
   int x , y , num , star , end;
   while(scanf("%d" , &n) && n){
      init();
      for(int i = 1 ; i <= n ; i++){
         for(int j = 1 ; j <= n ; j++){
            scanf("%d" , &num);
            if(num != -1)
              value[i][j] = num;
         }
      }
      for(int i = 1 ; i <= n ; i++)
         scanf("%d" , &charge[i]);

      floyd();

      while(1){
         scanf("%d%d" , &star , &end);
         if(star == -1 && end == -1)
           break;

         printf("From %d to %d :\n" , star , end);
         printf("Path: %d" , star);
         x = star , y = end;
         if(star != end){
            while(1){
                int p = path[x][y];
                printf("-->%d" , p);
                if(p == end)
                   break;
                x = p;
            }
         }
         printf("\n");
         printf("Total cost : %d\n\n" , value[star][end]);
      }
   }
   return 0;
}
时间: 2024-09-30 05:55:14

hdu 1385 Minimum Transport Cost的相关文章

HDU 1385 Minimum Transport Cost:最短路,打印字典序路径

链接: http://acm.hdu.edu.cn/showproblem.php?pid=1385 题目大意: 有N个城市,然后直接给出这些城市之间的邻接矩阵,矩阵中-1代表那两个城市无道路相连,其他值代表路径长度. 如果一辆汽车经过某个城市,必须要交一定的钱(可能是过路费). 现在要从a城到b城,花费为路径长度之和,再加上除起点与终点外所有城市的过路费之和. 求最小花费,如果有多条路经符合,则输出字典序最小的路径. 分析与总结: 1.   这题的关键在于按照字典序输出路径. 假设有 1---

zoj 1456 Minimum Transport Cost 最短路

   书上把这放在了bellman,但我觉得用floyd应该更加好写些     注意一个坑人的地方,就是测试数据中有自己到自己,输出是单独的n,而不是n-->n /* author:jxy lang:C/C++ university:China,Xidian University **If you need to reprint,please indicate the source** */ #include <iostream> #include <cstdio> #inc

hdu 1394 Minimum Inversion Number

hdu 1394 的传送门 Problem Description The inversion number of a given number sequence a1, a2, -, an is the number of pairs (ai, aj) that satisfy i < j and ai > aj. For a given sequence of numbers a1, a2, -, an, if we move the first m >= 0 numbers to

最短路专题【完结】

第一题 hdu 1317 XYZZY 点击打开hdu 1317 思路: 1 题目的图是一个有向图,并且可能存在环.第一个点的能量值为100,边的权值利用能量大小,例如2点为-60,如果1->2那么value[1][2] = -602 题目明确指出如果是要win的话,那么必须是经过的每条边都要大于0.那么我们只要把那些经过松弛操作后的点大于0的入队即可,小于等于0的点肯定不会出现在最终的路径上.3 如果存在正环的话,那么就有能量值无限大,那么这个时候只要判断这个点能否到达n4 判断是否是有环还是五

POJ 1385

Minimum Transport Cost Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4487    Accepted Submission(s): 1114 Problem Description These are N cities in Spring country. Between each pair of cities

.NET DateTime coding best practices

.NET DateTime coding best practicesAuthor:  Dan Rogers (danro), Microsoft Corporation January 9, 2004 SynopsisWriting programs that store, perform calculations and serialize time values using the .NET DateTime type requires an awareness of the differ

UVa 10954:Add All

链接: http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=113&page=show_problem&problem=1895 原题: Yup!! The problem name reflects your task; just add a set of numbers. But you may feel yourselves condescended, to wri

UVa 10670:Work Reduction

[链接] UVA:  http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=113&page=show_problem&problem=1611 poj:     http://poj.org/problem?id=1907 [原题] Paperwork is beginning to pile up on your desk, and tensions at the wo

树状数组专题【完结】

1 国外的论文点击打开链接 2 我的总结点击打开链接 任何能够造成树状数组下表为0的操作都会使得程序TLE,这是个很重要的地方! 第一题 poj 2299 Ultra-QuickSort 点击打开poj 2299 思路: 离散化+树状数组 分析: 1 题目的意思就是要求逆序数对 2 题目的输入个数有500000的规模但是每个数的最大值为999999999,因此我们需要离散化这些数据 3 对于数据9 1 0 5 4我们离散化成5 2 1 4 3 那么对于输入一个树a[i]我们去求一下它的离散化后的