最短路之双判断条件

问题 D: 最短路径问题

时间限制: 1 Sec  内存限制: 32 MB
提交: 41  解决: 13
[提交][状态][讨论版]

题目描述

给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。

输入

输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s,t;起点s,终点t。n和m为0时输入结束。
(1<n<=1000, 0<m<100000, s != t)

输出

输出 一行有两个数, 最短距离及其花费。

样例输入

3 2
1 2 5 6
2 3 4 5
1 3
0 0

样例输出

9 11

提示

拿到这题,第一印象就是最短路劲问题(题目写得清清楚楚)。当然,你可以直接套用最短路劲的解法。不过这里我要给大家介绍另一种解法,同样是图论里的算法——深度优先搜索。

从起点开始进行深度优先搜索,当搜索的结点到达终点时查看路径总长度与花费是否比已经得到的最短路径和最小花费小,如果要小的话就使用当前的路径和花费取代最短路径和最小花费。

当遍历到终点时是否就结束了?非也,还需要从其他路径遍历,判断其他路径是否又更短花费更小的。这里就需要用到回溯了。所谓回溯,就是还需要往回走来走其他的路径。那么会不会进入循环状态呢?对遍历过的结点进行标记就能够杜绝循环。当然需要在回溯时取消之前的标记。

提议概括:

  有n个顶点,m条无向路,每条路都有距离和花费两个权值,求最短路,若最短路有多条输出花费最小的那条。

解题分析:

  这道题只需对dijstra模板的判断条件进行一点的变化就可以了。需要注意的是,对于距离和花费这两个判断条件,他们的地位并不是平等的,而是以距离为第一判断条件,在最短距离相同时才判断花费。这就意味着对于花费也需要建一个像记录距离的dis数组一样去记录花费。同时,这道题也可以像题目提示那里说的一样,可以用深搜来写。下面会给出两种方法的代码。

AC代码:

深搜代码:

 1 #include<stdio.h>
 2 #include<string.h>
 3
 4 #define N 1005
 5
 6 struct node{
 7     int s, w;
 8 }e[N][N];//用一个二维结构体数组来记录从一个顶点到另一个顶点的距离和花费
 9
10 int maxs, maxw, n, m, t, s;
11 int book[N][N];
12
13 void dfs(int step, int we, int x)
14 {
15     int i, j, tx, ty;
16     if(x > n)//因为并不是搜索到终点就结束搜索,所以要把这个点所有能跑的点都搜一遍
17         return ;
18     if(x == t){//当到达终点时进行最短距离和最少花费的更新
19         if(step < maxs){//以距离为第一判断条件
20             maxs = step;
21             maxw = we;
22         }
23         else if(step == maxs && we < maxw)//当最短距离相等时再进行花费的判断
24             maxw = we;
25     }
26     for(i = 1; i <= n; i++){
27         if(book[x][i] == 0){
29             book[x][i] = -1;
30             dfs(step+e[x][i].s, we+e[x][i].w, i);
31             book[x][i] = 0;
32         }
33     }
34 }
35
36 int main()
37 {
38     int i, j,u , v, w, p;
39     node h;
40     while(scanf("%d%d", &n, &m), n || m){
41         maxs = maxw = 99999999;
42         memset(book, -1, sizeof(book));//初始化很重要,这里是把所有的点都初始化为不能走任何一个点
43         while(m--){
44             scanf("%d%d%d%d", &u, &v, &w, &p);
45                 e[u][v].s = e[v][u].s = w;
46                 e[u][v].w = e[v][u].w = p;
47                 book[u][v] = book[v][u] = 0;//当有路是标记为可以走
48         }
49         scanf("%d%d", &s, &t);
50         dfs(0, 0, s);
51         printf("%d %d\n", maxs, maxw);
52     }
53     return 0;
54 }

dijstra:

 1 #include<stdio.h>
 2 #include<string.h>
 3
 4 #define N 1005
 5 #define inf 99999999
 6
 7 int book[N], e[N][N], dis[N], h[N][N], hh[N];
 8
 9 int main()
10 {
11     int i, j, k, n, s, t, u, v, w, sum, f, Min, m, p;
12     while(scanf("%d%d", &n, &m), n || m){
13         memset(book, 0, sizeof(book));
14         for(i = 1; i <= n; i++)
15             for(j = 1; j <= n; j++){
16                 if(i == j) e[i][j] = h[i][j] = 0;
17                 else e[i][j] = h[i][j] = inf;
18             }
19
20         while(m--){
21             scanf("%d%d%d%d", &u, &v, &w, &p);
22             if(w < e[u][v])
23                 e[u][v] = e[v][u] = w;
24             if(p < h[u][v])
25                 h[u][v] = h[v][u] =  p;//将花费也存入一个地图中
26         }
27         scanf("%d%d", &s, &t);
28         for(i = 1; i <= n; i++){
29             dis[i] = e[s][i];
30             hh[i] = h[s][i];//记录起点到i点的最小花费
31         }
32         book[s] = f = 1;
33         while(f < n){
34             Min = inf;
35             for(i = 1; i <= n; i++)
36                 if(!book[i] && dis[i] < Min)
37                     Min = dis[i], j = i;
38             book[j] = 1;
39             f++;
40             for(i = 1; i <= n; i++){
41                 if(e[j][i] < inf && dis[i] >= e[j][i] + dis[j]){
42                     if(dis[i] > e[j][i]+dis[j]){//判断条件以距离为第一条件
43                         hh[i] = h[j][i]+hh[j];
44                         dis[i] = e[j][i]+dis[j];
45                     }
46                     else if(dis[i] == e[j][i]+dis[j] && hh[i] >= h[j][i]+hh[j])
47                         hh[i] = h[j][i]+hh[j];
48                 }
49             }
50         }
51         printf("%d %d\n", dis[t], hh[t]);
52     }
53     return 0;
54 }
时间: 2024-10-09 05:58:29

最短路之双判断条件的相关文章

Shell中条件判断语法与判断条件

一,简介 Shell各种判断结构和运算符的用法是shell编程的基础,了解shell的判断.运算符和一些退出状态 对后面的学习有很重要的影响.shell有一个内部命令test经常用于对判断语句 进行测试一种或几种状态的条件是否成立 二. 判断条件 (1)Linux的shell中的测试命令,用于测试某种条件或某几种条件是否真实存在 测试命令是判断语句和循环语句中条件测试的工具,对判断和运算符的比较测试有很大的帮助. (2)测试条件为真,返回一个0值:      为假,返回一个非0整数值 测试命令有

js--运算符与或非 及 if判断条件、隐式转换 介绍

逻辑运算符: 返回值是Boolean类型,一般连接多个比较表达式: 与(&&):当所有表达式都返回true时,结果才为true,即是遇false则false: 或(||):当所有表达式都返回false时,结果才为false,即是遇true则true: 与(&&)也称短路与,意思是当遇到第一个为false的表达式时,该后面的表达式不再执行,结果直接返回false: 或(||)也称短路或,意思是当遇到第一个为true的表达式时,该后面的表达式不再执行,结果直接返回true: i

.Net程序员之Python基础教程学习----判断条件与循环[Fourth Day]

    今天学习Python的判断条件与循环操作. 一. 布尔变量: 在学习判断条件之前必须的了解bool变量,在Python中bool变量与C语言比较类似,与.net差别比较大,其中下面集中情况需要记住. False, '', 0, (), [],{},None 为空,而True,12,'hello',[1] 这些普遍都为真. 其实可以简单理解为,无即是false,有既是true >>> bool(True) True >>> bool(0) False >&g

[Shell]if 常用判断条件

IF 判断 之前也写过简单的shell脚本,也不是转职运维,和系统相关的工作比较少,所以不怎么熟练. 最近由于系统总是出现各种乱七八糟的问题,也没有人来协助,只好自己写shell脚本了,都是些基础的脚本,但由于shell的语法和通常的高级语言有些不一样,所以还是要系统的看下常用的部分. if语句就是很重要的一个. 这种文章很多,只是拿来主义,如果有心得体会也会加上,小计下以后备查. 基本结构:  if语句块需要使用if结束 if condition then statements elif co

STL--G - For Fans of Statistics(两个判断条件-二分)

G - For Fans of Statistics Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Description Have you ever thought about how many people are transported by trams every year in a city with a ten-million population

ThinkPHP3.2中if判断条件是两个变量

<select name="typeId"> <foreach name="typeInfo" item="v"> <if condition="$v[typeId] eq $article[typeId]"> <option value="{$v.typeId}" selected>{$v.name}</option> <else/>

Shell脚本IF条件判断和判断条件总结

转自:http://m.jb51.net/article/56553.htm 这篇文章主要介绍了Shell脚本IF条件判断和判断条件总结,本文先是给出了IF条件判断的语法,然后给出了常用的判断条件总结,需要的朋友可以参考下 前言:      无论什么编程语言都离不开条件判断.SHELL也不例外. if list then           do something here       elif list then           do another thing here       e

vba中if判断条件里等号无法完成赋值操作

今天遇到一个问题,结果发现是因为vba中if的判断条件中等号("=")无法完成赋值操作造成的. 举个栗子: 故应该在if之前就完成必要的赋值操作: 所以,if判断条件里的等号("=")只能用于判断相等,不能用于赋值.

MyBatis 判断条件为等于的时候,常量需要加 .toString()

当MyBatis 判断条件为等于的时候,常量需要加 .toString() 来转换,这种方法是稳定的,推荐使用,比如: <!-- 正确的,稳定,推荐使用 --> <if test="newsImage != null and newsImage == '0'.toString()"> <![CDATA[ and len(newsImage) > 0 ]]> </if> 参考网址