hdu 1385 求字典序最小的最短路

需要注意的是这个题不仅有边权还有点权,起点和终点的点权不算。

思路还是一样,只是把路过的点的点权也加上再松弛即可。另外,距离相等的时候需要判断一下,选择字典序小的链连到这个点,方法就是把这个点以及之前的点放到栈里比较。

  1 #include <algorithm>
  2 #include <iostream>
  3 #include <cstring>
  4 #include <stack>
  5 #include <cstdio>
  6 using namespace std;
  7
  8 const int INF = 100000001;
  9 const int N = 10001;
 10 int graph[N][N];
 11 int dist[N];
 12 int tax[N];
 13 int pre[N];
 14 bool visit[N];
 15 int n, m;
 16
 17 bool lessThan( int cur, int x, int y )
 18 {
 19     stack<int> sx, sy;
 20     //注意:cur必须也放到栈里
 21     sx.push(cur);
 22     sy.push(cur);
 23     while ( x != -1 )
 24     {
 25         sx.push(x);
 26         x = pre[x];
 27     }
 28     while ( y != -1 )
 29     {
 30         sy.push(y);
 31         y = pre[y];
 32     }
 33     while ( !sx.empty() && !sy.empty() )
 34     {
 35         if ( sx.top() != sy.top() ) return sx.top() < sy.top();
 36         sx.pop();
 37         sy.pop();
 38     }
 39     return sx.size() < sy.size();
 40 }
 41
 42 void dij( int s, int t )
 43 {
 44     memset( visit, false, sizeof(visit) );
 45     for ( int i = 0; i <= n; i++ )
 46     {
 47         dist[i] = INF;
 48     }
 49     dist[s] = 0;
 50     pre[s] = -1;
 51     for ( int i = 1; i <= n; i++ )
 52     {
 53         int u = 0;
 54         for ( int j = 1; j <= n; j++ )
 55         {
 56             if ( !visit[j] && dist[j] < dist[u] )
 57             {
 58                 u = j;
 59             }
 60         }
 61         visit[u] = true;
 62         for ( int j = 1; j <= n; j++ )
 63         {
 64             if ( visit[j] ) continue;
 65             int d = dist[u] + graph[u][j] + tax[j];
 66             if ( d < dist[j] )
 67             {
 68                 dist[j] = d;
 69                 pre[j] = u;
 70             }
 71             else if ( d == dist[j] && lessThan( j, u, pre[j] ) )
 72             {
 73                 pre[j] = u;
 74             }
 75         }
 76     }
 77 }
 78
 79 void out( int i )
 80 {
 81     if ( pre[i] == -1 )
 82     {
 83         printf("Path: %d", i);
 84     }
 85     else
 86     {
 87         out( pre[i] );
 88         printf("-->%d", i);
 89     }
 90 }
 91
 92 int main ()
 93 {
 94     while ( scanf("%d", &n), n )
 95     {
 96         for ( int i = 1; i <= n; i++ )
 97         {
 98             for ( int j = 1; j <= n; j++ )
 99             {
100                 scanf("%d", &graph[i][j]);
101                 if ( graph[i][j] == -1 )
102                 {
103                     graph[i][j] = INF;
104                 }
105             }
106         }
107         for ( int i = 1; i <= n; i++ )
108         {
109             scanf("%d", tax + i);
110         }
111         int s, t;
112         while ( scanf("%d%d", &s, &t) != EOF )
113         {
114             if ( s == -1 || t == -1 ) break;
115             int tmp = tax[t];
116             tax[t] = 0;
117             dij( s, t );
118             tax[t] = tmp;
119             printf("From %d to %d :\n", s, t);
120             out( t );
121             printf("\nTotal cost : %d\n\n", dist[t]);
122         }
123     }
124     return 0;
125 }
时间: 2024-10-06 15:07:01

hdu 1385 求字典序最小的最短路的相关文章

HDU 5335 Walk Out(Bfs搜索字典序最小的最短路)

 题意:nXm的地图, 问通过四个方向从(1,1)走到(1000,1000)所经过的最小二进制序列是多少,忽略前缀0. 思路:首先如果起点为0,那么我们bfs搜索和起点0联通的为0的连通块,这样我们第一步肯定是从与这个连通块相邻的且与重点最近的地方出发. 将所有可能起点加入队列,在bfs一遍找到字典序最小的那条路就是答案, 在这里可以用两个vector类型容器,一个是q2存储所有节点值存为0的结点, 另一个q3存储节点值为1的结点. 那么如果q2不为空那么也就是有可以走零,那么就从这里面选,

[poj2337]求字典序最小欧拉回路

注意:找出一条欧拉回路,与判定这个图能不能一笔联通...是不同的概念 c++奇怪的编译规则...生不如死啊... string怎么用啊...cincout来救? 可以直接.length()我也是长见识了... CE怎么办啊...g++来救? #include<cstdio> #include<iostream> #include<cstring> #include<cmath> #include<algorithm> #define N 2020

HDU 5294--Tricks Device【最小割 &amp;&amp; 最短路处理,新建图】

Tricks Device Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2208    Accepted Submission(s): 584 Problem Description Innocent Wu follows Dumb Zhang into a ancient tomb. Innocent Wu's at the en

sdut3562-求字典序最小的最短路 按顶点排序后spfa的反例

首先我们可以这么搞...倒序建图,算出源点s附近的点距离终点的距离,然后判断一下,终点是否能跑到源点 能跑到的话呢,我们就判断s周围的点是否在最短路上,然后我们选编号最小的点就好了 代码 #include <iostream> #include <cstdio> #include <algorithm> #include <queue> #include <vector> #include <cstring> using namesp

HDU 1385 Minimum Transport Cost (字典序打印最短路)

题意  给你一个无向图的邻接矩阵  和途径每个点需要的额外花费首尾没有额外花费  求图中某两点之间的最短路并打印字典序最小路径 要求多组点之间的就用floyd咯  打印路径也比较方便  nex[i][j]表示从i点到j点最短路的第一个途经点  那么如果路径中加入一个节点k后 nex[i][j]应该更新为nex[i][k]  因为要途径k了 #include<cstdio> #include<cstring> using namespace std; const int N = 10

HDU 1385 Minimum Transport Cost(Floyd 最短路 打印路径)

HDU 1385 大意: 有N个城市,然后直接给出这些城市之间的邻接矩阵,矩阵中-1代表那两个城市无道路相连,其他值代表路径长度. 如果一辆汽车经过某个城市,必须要交一定的钱(可能是过路费). 现在要从a城到b城,花费为路径长度之和,再加上除起点与终点外所有城市的过路费之和. 求最小花费,如果有多条路经符合,则输出字典序最小的路径. 思路: Floyd求最短路,打印路径即可. 1 /*--------------------------------------------------------

HDU - 1385 Minimum Transport Cost(floyd+字典序)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1385 题意:给出一个邻接矩阵(对应位置的值代表两个顶点之间的花费),并且到达另外一个位置还要加上那个位置对应的额外花费. 然后求出最少的花费和起点到终点的路径(如果两条路径花费一样,求出字典序最小的) 求任意两点间的最小花费,一般都采用Floyd.Floyd就是一个简单的dp思想,在用Floyd的时候记录一下路径就可以了. 这里要求字典序,可以在路径相等的时候再次进行判断一下,取小的顺序. 1 #i

HDU 4738 Caocao&#39;s Bridges(求价值最小的桥)

Problem Description Caocao was defeated by Zhuge Liang and Zhou Yu in the battle of Chibi. But he wouldn't give up. Caocao's army still was not good at water battles, so he came up with another idea. He built many islands in the Changjiang river, and

HDU 2485 求删最少点使得 边权=1的有向图最短路&gt;k

题意: 给定n个点 m条有向边 k 下面m条有向边 问删最少几个点使得1-n的最短路>k 10 11 5 1 2 2 3 3 4 4 5 5 10 2 9 1 6 6 7 7 8 8 9 9 10 8 10 5 1 2 2 3 3 4 4 5 5 6 6 8 1 7 7 8 4 7 7 4 #include <stdio.h> #include <string.h> #define N 55 #define INF 1<<30 #define eps 1e-5 i