最短路径问题,首先想到了贪心算法实现的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
****************************************************************/