九度 题目1008:最短路径问题

最短路径问题,首先想到了贪心算法实现的dijkstra算法;这道题我用了链表的存储方式,其实用邻接矩阵也可以,主要为了练手,并且链表比矩阵要节约空间;

题目描述:

给你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
AC代码如下(主要运用了链表+Dijkstra算法):

#include
<stdio.h>

#include
<string.h>

#define
inf 10000000

const

int

Maxn = 200005;

int

N,M;

int

visit[1001];//标记某个节点是否被求出最短距离

int

first[1001];//存储每个节点为始点的链表的第一个边的标号

struct

Edge{

    int

target;
//终点

    int

next;
//下一条边的标号

    int

dt,ct;
//边的长度和花费

}edge[Maxn];

struct

BNode{

    int

dist,cost;

}Node[1001];//到达某点的最短路和花费

//相当于链表的头插发,很有意思。比用邻接矩阵高效多了

void

addEdge(
int

index,
int

u,
int

v,
int

d,
int

c){

    edge[index].next
= first[u];
//将这条边插入到u为初始节点的链表的头结点处

    edge[index].target
= v;

    edge[index].dt
= d;

    edge[index].ct
= c;

    first[u]
= index;

}

int

findMinNode(){
//在剩下的所有节点中找最小的

    int

i, Max = inf;

    int

index = 0;

    for(i
= 1; i <= N; i++){

        if(Node[i].dist
< Max && !visit[i]){

            Max
= Node[i].dist;

            index
= i;

        }

    }

    return

index;

}

void

dijk(
int

s){

    int

i;

    int

flag = 1;

    Node[s].cost
= Node[s].dist = 0;

    while(flag
< N){
//更新N-1次

        int

x = findMinNode();

        if(!x)
break;

        visit[x]
= 1;

        flag++;

        for(i
= first[x]; i != -1; i = edge[i].next){

            int

target = edge[i].target;

            if(Node[x].dist
+ edge[i].dt < Node[target].dist && !visit[target]){
//更新节点

                Node[target].dist
= Node[x].dist + edge[i].dt;

                Node[target].cost
= Node[x].cost + edge[i].ct;

            }else

if
(Node[x].dist
+ edge[i].dt == Node[target].dist && !visit[target]){

            //如果存在多条路径,更新最小花费节点

                if(Node[x].cost
+ edge[i].ct < Node[target].cost){

                    Node[target].cost
= Node[x].cost + edge[i].ct;

                }

            }

        }

    }

}

int

main(){

    int

u, v, d, c;

    int

s, t;

    while(scanf("%d
%d"
,&N,&M)
!= EOF && (N != 0 || M != 0)){

        int

index = 0;

        memset(first,-1,sizeof(first));

        for(int

i = 1; i <= N; i++){

            Node[i].dist
= Node[i].cost = inf;

        }

        memset(visit,
0,
sizeof(visit));

        for(int

i = 0; i < M; i++){

            scanf("%d
%d %d %d"
,&u,&v,&d,&c);

            addEdge(index,
u, v, d, c);

            index++;

            addEdge(index,
v, u, d, c);

            index++;

        }

        scanf("%d
%d"
,
&s, &t);

        dijk(s);

        printf("%d
%d\n"
,Node[t].dist,Node[t].cost);

    }

}

/**************************************************************

    Problem:
1008

    User:
姜超

    Language:
C++

    Result:
Accepted

    Time:10
ms

    Memory:4160
kb

****************************************************************/

时间: 2024-10-13 15:59:02

九度 题目1008:最短路径问题的相关文章

九度 题目1335:闯迷宫 题目1365:贝多芬第九交响曲

转载请注明本文地址http://blog.csdn.net/yangnanhai93/article/details/40718149 简单说说宽度优先搜索BFS 说实话,这是第一个自己写的宽度优先搜索的题目,之前也是不太明白之间的区别,好吧,只能说自己学的太渣-- 言归正传,对于初学者来说,可能最大的概念就是一个是深度搜索,一个是宽度搜索,好吧,我表示废话了,我其实就是这个样子的,然后一直不得甚解...所以第一次上来,我就直接搜索DFS,结果太明显,就是TLE或者MLE,然后就抓狂中,这可能是

九度 题目1411:转圈

题目链接http://ac.jobdu.com/problem.php? pid=1411 转载请注明本文链接http://blog.csdn.net/yangnanhai93/article/details/41315349 这个题目,好难-- 这个题目是自己瞎搞弄出来的答案.不知道有没有更优的方法,可是.也说下自己的思路好了 首先明白题目要求.要先从点s出发,然后最短的回到s的路径.所以必定有两种情况 1:出发之后回不来 2:出发之后回来 好吧.确实有点废话,如果第一个到的点为t 则1和2的

九度 题目1144:Freckles

题目描写叙述: In an episode of the Dick Van Dyke show, little Richie connects the freckles on his Dad's back to form a picture of the Liberty Bell. Alas, one of the freckles turns out to be a scar, so his Ripley's engagement falls through. Consider Dick's

九度 题目1123:采药

题目描述: 辰辰是个很有潜能.天资聪颖的孩子,他的梦想是称为世界上最伟大的医师. 为此,他想拜附近最有威望的医师为师.医师为了判断他的资质,给他出了一个难题. 医师把他带到个到处都是草药的山洞里对他说: "孩子,这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值. 我会给你一段时间,在这段时间里,你可以采到一些草药.如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大." 如果你是辰辰,你能完成这个任务吗? 输入: 输入的第一行有两个整数T(1 <=

九度 题目1122:吃糖果

题目描述: 名名的妈妈从外地出差回来,带了一盒好吃又精美的巧克力给名名(盒内共有 N 块巧克力,20 > N >0). 妈妈告诉名名每天可以吃一块或者两块巧克力. 假设名名每天都吃巧克力,问名名共有多少种不同的吃完巧克力的方案. 例如: 如果N=1,则名名第1天就吃掉它,共有1种方案: 如果N=2,则名名可以第1天吃1块,第2天吃1块,也可以第1天吃2块,共有2种方案: 如果N=3,则名名第1天可以吃1块,剩2块,也可以第1天吃2块剩1块,所以名名共有2+1=3种方案: 如果N=4,则名名可以

九度 题目1205:N阶楼梯上楼问题

题目描述: N阶楼梯上楼问题:一次可以走两阶或一阶,问有多少种上楼方式.(要求采用非递归) 输入: 输入包括一个整数N,(1<=N<90). 输出: 可能有多组测试数据,对于每组数据, 输出当楼梯阶数是N时的上楼方式个数. 样例输入: 4 样例输出: 5 分析:第n阶台阶的方法等于上到第n-1阶台阶的方法加上第n-2阶的台阶的方法之和,因为89阶的时候已经超过2的32次方,所以用long long int 代码如下: #include <stdio.h> long long int

九度 题目1448:Legal or Not

判断是否存在环的问题,本文采用的是拓扑排序,如果输出的节点少于N,则形成了环,和之前的1449几乎是一样的代码 题目链接http://ac.jobdu.com/problem.php?pid=1448 转载请注明本文地址http://blog.csdn.net/yangnanhai93/article/details/41226369 #include <iostream> #include <memory.h> #include <queue> using names

九度 题目1449:确定比赛名次

很明显的拓扑排序问题,绘制成图之后会发现很好理解,刚开始我自己也不是很理解,画图之后思路特别清晰 转载请注明本文地址http://blog.csdn.net/yangnanhai93/article/details/41226221 题目链接http://ac.jobdu.com/problem.php?pid=1449 #include <iostream> #include <memory.h> #include <queue> using namespace st

九度-题目1011:最大连续子序列

题目描述:     给定K个整数的序列{ N1, N2, ..., NK },其任意连续子序列可表示为{ Ni, Ni+1, ..., Nj },其中 1 <= i <= j <= K.最大连续子序列是所有连续子序列中元素和最大的一个,例如给定序列{ -2, 11, -4, 13, -5, -2 },其最大连续子序列为{ 11, -4, 13 },最大和为20.现在增加一个要求,即还需要输出该子序列的第一个和最后一个元素. 输入: 测试输入包含若干测试用例,每个测试用例占2行,第1行给出