两种最短路算法(spfa以后再加)

最短路是指一个图状结构中点a到点b的最短距离,常用到两种算法来解题。

Dijkstra算法:

思想:

Dijkstra算法是利用贪心的思想,从已知的最短距离点开始,更新相邻顶点的最短距离,之后将这个点排除。用于单源最短路问题。


题目:

hdoj : http://acm.hdu.edu.cn/showproblem.php?pid=2066

思路:

这个题看似是多源的,但实际上只要把出发点设为0,出发点到相邻点距离为0即可。

AC代码:

#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
const int M = 1010;
const int INF = 0xfffffff;
int road[M][M], d[M], ss[M], des[M];//以road[a][b]来表示点a到点b的距离(点b到点a为road[b][a]) d[i]来存储出发点到点i的最短距离 一直更新这个距离
bool vis[M];//vis来标记排除的点
void dijkstra()
{
    while(1)//刚开始循环时只有起点符合条件,循环到后面符合条件的点都被标记了
    {
        int m = INF, dx;
        for(int i = 0; i < M; i++)//寻找距离最短的点
            if(!vis[i] && d[i] < m)
            {
                m = d[i];
                dx = i;
            }
        if(m == INF)
            break;
        vis[dx] = true;
        for(int i = 0; i < M; i++)
            if(!vis[i])
                d[i] = min(d[i], d[dx] + road[dx][i]);//更新到达与该点相邻的点的最短距离
    }
}
main()
{
    int t, s, p;
    while(~scanf("%d %d %d", &t, &s, &p))
    {
        fill(vis, vis + M, 0);
        fill(&road[0][0], &road[0][0] + M * M, INF);
        fill(d, d + M, INF);
        while(t--)
        {
            int a, b, time;
            scanf("%d %d %d", &a, &b, &time);
            road[a][b] = road[b][a] = min(time, road[a][b]);
        }
        for(int i = 0; i< s; i++)
        {
            scanf("%d", &ss[i]);
            road[ss[i]][0] = road[0][ss[i]] = 0;
            d[ss[i]] = 0;
        }
        for(int i = 0; i < p; i++)
            scanf("%d", &des[i]);
        d[0] = 0;
        dijkstra();
        int res = INF;
        for(int j = 0; j < p; j++)
            res = min(res, d[des[j]]);
        printf("%d\n", res);
    }
}


Floyd算法:

利用动态规划的思想,计算经过点i到点j之间的路径,特点是代码十分好写,并且其结果是图中所有相连点的任意两点间的最短距离,但是耗时很长,时间复杂度为O(n ^ 3)。

题目:

hdoj : http://acm.hdu.edu.cn/showproblem.php?pid=2544

思路:

这道题数据范围并不大,可以漂亮地用Floyd算法解决。注意距离是无向的,要正反赋值。

AC代码:

#include<iostream>
#include<algorithm>
using namespace std;
const int M = 110;
int len[M][M];//len[a][b]记录点a到点b的有向距离
main()
{
	int n, m;
	while(~scanf("%d %d", &n, &m))
	{
		if(n == 0 && m == n)
			break;
		for(int i = 0; i < M; i++)
			for(int j = 0; j < M; j++)
				len[i][j] = 999999;
		while(m--)
		{
			int a, b, c;
			scanf("%d %d %d", &a, &b, &c);
			len[a][b] = c;
			len[b][a] = c;
		}
		len[1][1] = 0;
		for(int k = 1; k < M; k++)//中间点
			for(int i = 1; i < M; i++)//起始点
				for(int j = 1; j < M; j++)//终点 顺序不能乱 
					len[i][j] = min(len[i][j], len[i][k] + len[k][j]);
			printf("%d\n", len[1][n]);
	}
}

Dijkstra算法可以用堆对其优化,以下是2544用堆优化的Dijkstra算法AC代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
const int INF = 1e9;
const int M = 110;
int n, m, d[M][M], l[M];
typedef pair <int, int> P;
priority_queue<P, vector<P>, greater<P> > q;
void dijstra()
{
    while(!q.empty())
        q.pop();
    q.push(P(0, 1));
    while(!q.empty())
    {
        P p = q.top();
        q.pop();
        if(l[p.second] < p.first)
            continue;
        for(int i = 2; i < M; i++)
            if(d[p.second][i] != INF && l[i] > l[p.second] + d[p.second][i])
            {
                l[i] = l[p.second] + d[p.second][i];
                q.push(P(l[i], i));
            }
    }
}
main()
{
    while(~scanf("%d %d", &m, &n))
    {
        fill(&d[0][0], &d[0][0] + M * M, INF);
        fill(l, l + M, INF);
        if(m == n && m == 0)
            break;
        l[1] = 0;
        for(int i = 0; i < n; i++)
        {
            int a, b, c;
            scanf("%d %d %d", &a, &b, &c);
            d[a][b] = d[b][a] = min(d[a][b], c);
        }
        dijstra();
        cout << l[m] << endl;
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值