最短路径问题 迪杰斯特拉

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

Input

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

Output

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

Sample Input

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

Sample Output

9 11

入门迪杰斯特拉 单源最短路问题



本人不会绘图以上图片来自网络

1 :初始化,开每个元素都是无限大的map【i】【j】,cost [i][j]图(数组),i,j;代表结点(就像图中的字母),cost的值代表价值,map的价值代表距离;然后输入元素;进行算法;

详细在代码中介绍;

时间有限,以后再填充;

代码详解

友情提示非纯c++有超时点;后面会标记;

//先让我bb几句,他喵的好累,好楼,思路这么简单的代码,还花这么长时间,还在以前不是很理解的情况下打过几边,

//幸运的是我现在已经了解他的每一个私处,卧槽,怎么快变成色情小说了,//滑稽;

//源码看一个小时,写出来,一个小时,找错误,一个小时,重新写,30min,找错误一个小时

//希望大家可以认真学习这个算法,如果你很聪明请例外,我这么low,只有多理解了,先之后每天打一边,一个月后我才能向你保证我可以流畅的使用迪杰斯特拉了。

i,j代表接结点(就是连接点)

flag【】代表状态,//这个是单源问题,不能重复走

#include<stdio.h>
#include<string.h>
int i, j, n, m, a, b, d, p;
#define inf 999999
int map[1001][1001], cost[1001][1001];
int  flag[1001], value[1001], dis[1001];
void DJ(int st, int en)
{
for (i = 1; i <= n; i++)
{
dis[i] = map[st][i];
value[i] = cost[st][i];
}//初始化头节点,
memset(flag, 0, sizeof(flag));//初始化状态
flag[st] = 1;//头节点标记为1 ,不能再便利到他;
int v;


//在循环中的主要是实现没走和走之后的状态,综合贪心和dp思想;
for (i = 1; i <= n; i++)
{
int MIN = inf;//这个很重要//
for (j = 1; j <= n; j++)
{
if (!flag[j] && MIN > dis[j])
{
v = j;
MIN = dis[j];
}
}//找到1,2节点之间的最短距离;
flag[v] = 1;//标记
if (MIN == inf) break;
for (j = 1; j <= n; j++)
{
if (!flag[j] && map[v][j] < inf)//这个点没被查找过,且节点之间是可以走的
{
if (!flag[j] && dis[j] > map[v][j] + dis[v])//最关键,在第一次循环时dis【j】的值是inf,


//可以把他看作一个最大值,用它来遍历求得最小值
{
dis[j] = map[v][j] + dis[v];
value[j] = value[v] + cost[v][j];
}//保存数据
else if (dis[j] == map[v][j] + dis[v] && value[j] > value[v] + cost[v][j])
value[j] = value[v] + cost[v][j];//保存最小价值;
}
}
}
printf("%d %d\n", dis[en], value[en]);
}
int main()
{
while (~scanf("%d%d", &n, &m) && (n || m))
{


for (i = 1; i <= n; i++)
for (j = 1; j <= n; j++)
{
map[i][j] = inf;
cost[i][j] = inf;
}//不用memset初始化,那个没这个快;
while (m--)
{
scanf("%d%d%d%d", &a, &b, &d, &p);
if (map[a][b] > d || (map[a][b] == d && cost[a][b] > p))//存图,在节点之间有联系的情况记录下
{
map[a][b] = map[b][a] = d;
cost[a][b] = cost[b][a] = p;
}
}
int ss, ee;
scanf("%d%d", &ss, &ee);
DJ(ss, ee);
}
return 0;
}















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值