Dijkstra算法--代码模板

自己对Dijstra算法的理解是:

  1. 首先输入保存点,边的权值(注意无向图和有向图在保存时的区别)。
  2. 将表示从起点st到顶点 i 的距离的d[ i ]数组的每一个值初始化为INF,令d[st] = 0。
  3.  遍历d[ ]数组的下标 i (即顶点 i)这个操作是通过优先队列来实现的,然后遍历以顶点 i 为起点的边,更新d[ i ]的最小值。
  4. 最后直接访问d[en],即可得到最短距离。

通过模板题来熟悉一下这个算法吧,最短路之HDU2544

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
#define INF 0x3f3f3f3f
#define FRE() freopen("in.txt","r",stdin)

using namespace std;
typedef long long ll;
typedef pair<int,int> P;//first是距离,second是点的编号
const int maxn = 150;
int d[maxn];//数组d[i]表示从起点s到顶点 i 的最短距离
int n,m;
struct edge
{
    edge(int t,int c):to(t),cost(c){}
    int to;//表示这条边的终点
    int cost;//该边的权重
};
vector<edge> G[maxn];//储存以下标i为起点的边
priority_queue<P,vector<P>,greater<P> > que;//遍历d[]数组的下标,更新最小值

void init()
{
    for(int i = 0; i < maxn; i++)
        G[i].clear();
    for(int i = 0; i < m; i++)
    {
        int st,en,c;
        scanf("%d%d%d",&st,&en,&c);
        G[st].push_back(edge(en,c));//这是个无向图注意储存的方式
        G[en].push_back(edge(st,c));
    }
}

int main()
{
    //FRE();
    while(scanf("%d%d",&n,&m) && n+m)
    {
        init();
        for(int i = 0; i < maxn; i++)
            d[i]= INF;
        d[1] = 0;//起点到起点本身的距离为0
        que.push(P(0, 1));
        while(!que.empty())
        {
            P p = que.top();
            que.pop();
            int v = p.second;
            if(d[v] < p.first) continue;
            for(int i = 0; i < G[v].size(); i++)
            {
                edge e = G[v][i];
                if(d[e.to] > d[v] + e.cost)
                {
                    d[e.to] = d[v] + e.cost;
                    que.push(P(d[e.to],e.to));
                }
            }
        }
        printf("%d\n",d[n]);
    }
    return 0;
}

另外还有一个用二维数组的写法

#include <iostream>
#include <cstring>
#include <cstdio>
#define INF 0x3f3f3f3f

using namespace std;
const int maxn = 100;

int e[maxn][maxn];
int dis[maxn],vis[maxn];
int n,m;

void init()
{
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= n; j++)
        {
            e[i][j] = INF;
        }
    }
    int a,b,c;
    for(int i = 0; i < m; i++)
    {
        scanf("%d%d%d",&a,&b,&c);
        e[a][b] = c;
        e[b][a] = c;
    }
    for(int i = 1; i <= n; i++)//算出1到各个点的距离
    {
        dis[i] = e[1][i];
        vis[i] = 0;
    }
    vis[1] = 1;
}

void Dij()
{
    for(int i = 1; i <= n; i++)
    {
        int mmin = INF;
        int u;
        for(int j = 1; j <= n; j++)
        {
            if(!vis[j] && dis[j] < mmin)
            {
                mmin = dis[j];
                u = j;
            }
        }
        vis[u] = 1;
        for(int j = 1; j <= n; j++)
        {
            if(!vis[j] && dis[j] > e[u][j] + dis[u])
            {
                dis[j] = e[u][j] + dis[u];
            }
        }
    }
}

int main()
{
    while(scanf("%d%d",&n,&m) && (m + n))
    {
        init();
        Dij();
        printf("%d\n",dis[n]);
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Dijkstra算法是一种用于解决带权图的单源最短路径问题的贪心算法。它维护一个距离起点的最短路径已知的顶点集合,通过不断地扩展这个集合,最终得到从起点到所有顶点的最短路径。 Dijkstra算法的基本思想是,维护一个集合S,表示已经求出最短路径的顶点集合。一开始,S只包含起点。然后,每次从集合V-S中选取一个距离起点最近的顶点u,将其加入集合S中,并更新与u相邻的所有顶点的最短路径。 具体实现上,我们可以使用一个数组dis[]来存储每个顶点到起点的最短路径长度,数组vis[]表示该顶点是否已经被加入到集合S中。每次选取距离起点最近的顶点u后,我们遍历u的所有邻居v,并更新dis[v]的值,如果dis[v]发生了改变,我们就将v加入到一个优先队列中,等待下一次选择。 以下是Dijkstra算法的伪代码实现: ``` int n; // 顶点数 int dis[N]; // 存储起点到每个顶点的最短距离 bool vis[N]; // 标记每个顶点是否已经加入集合S中 vector<pair<int, int>> adj[N]; // 存储每个顶点的邻居 void dijkstra(int s) { // s为起点编号 memset(dis, 0x3f, sizeof dis); // 将dis数组初始化为无穷大 dis[s] = 0; // 起点到自身的距离为0 priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q; q.push({0, s}); // 将起点加入队列中 while (!q.empty()) { auto t = q.top(); q.pop(); int u = t.second; if (vis[u]) continue; // 如果该点已经在集合S中,直接跳过 vis[u] = true; // 将u加入集合S中 for (auto [v, w] : adj[u]) { // 遍历u的所有邻居 if (dis[v] > dis[u] + w) { // 如果从u到v的距离更短 dis[v] = dis[u] + w; // 更新dis数组 q.push({dis[v], v}); // 将v加入队列中 } } } } ``` 其中,priority_queue是一个优先队列,用于存储待选顶点。我们使用了STL中的pair来表示顶点与其到起点的距离。优先队列默认按照pair的第一个元素排序,因此我们需要自定义一个比较函数,将pair按照第二个元素(距离)排序。 Dijkstra算法的时间复杂度为O(ElogV),其中E为边数,V为顶点数。在实际应用中,Dijkstra算法的效率很高,能够处理大规模的图。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值