【模板】Dijkstra迪杰斯特拉算法【含标记路径】

标记路径的迪杰斯特拉算法【Dijkstra】

#include<bits/stdc++.h>
using namespace std;
#define maxn 505
int n,m,cnt,x,y,fir[maxn],ans[maxn],vis[maxn],way[maxn];
struct edge
{
    int v,w,nxt;
}es[20005];
void mysum(int a,int b,int c)
{
    es[++cnt].v=b;
    es[cnt].w=c;
    es[cnt].nxt=fir[a];
    fir[a]=cnt;
}
void dj(int x)
{
    memset(ans,0x3f,sizeof(ans));
    ans[x]=0;vis[x]=1;
    for(int i=1;i<n;i++)
    {
        for(int j=fir[x];j;j=es[j].nxt)
        {
            int yy=es[j].v;
            if(ans[yy]>ans[x]+es[j].w)
            {
                ans[yy]=ans[x]+es[j].w ;
                way[yy]=x;
            }
        }
        int minn=1000005;
        for(int i=1;i<=n;i++)
        {
            if(vis[i]==0)
                if(ans[i]<minn)
                {
                    minn=ans[i];
                    x=i;
                }
        }
        if(x==y)
            break;
        vis[x]=1;
    }
}
void myout(int q)
{
    if(way[q]==0)
        return;
    else
    {
        myout(way[q]);
        printf("%d ",way[q]);
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        mysum(a,b,c);
    }
    scanf("%d%d",&x,&y);
    dj(x);
    printf("%d\n",ans[y]);
    myout(y);
    printf("%d ",y);
}

题目描述
有向图的单源点最短路问题(Dijkstra算法)
输入
第1行:2个空格分开的整数n(2<=n<=500)和m(10<=m<=20000),分别表示图的顶点数和边数。
第2…m+1行:每行3个空格分开的整数i,j, w。i表示一条边的起点,j表示终点, w表示权值。
第m+2行:2个整数s,t(1<=s,t<=n),表示指定的顶点。
输出
第1行:最小距离
第2行:最短路径(从起点到终点的序列,用1个空格分开)
样例输入 Copy
5 7
1 2 10
1 4 30
1 5 100
2 3 50
3 5 10
4 3 20
4 5 60
1 5
样例输出 Copy
60
1 4 3 5

下面是用邻接表实现的迪杰斯特拉算法模板: ```c++ #include <iostream> #include <vector> #include <queue> #include <cstring> using namespace std; const int MAXN = 1005; // 最大顶点数 const int INF = 0x3f3f3f3f; // 无穷大 struct Edge { int to, w; Edge(int to, int w): to(to), w(w) {} }; vector<Edge> G[MAXN]; // 邻接表存图 int dis[MAXN]; // 从源点到各个顶点的最短距离 bool vis[MAXN]; // 记录每个顶点是否已经被访问过 void dijkstra(int s) { memset(dis, INF, sizeof(dis)); // 初始化最短距离为无穷大 memset(vis, false, sizeof(vis)); // 初始化所有顶点为未访问过 dis[s] = 0; // 源点到自己的距离为0 priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q; q.push(make_pair(0, s)); // 将源点加入到优先队列中 while (!q.empty()) { int u = q.top().second; // 取出当前距离最短的顶点 q.pop(); if (vis[u]) continue; // 如果该顶点已经访问过,则跳过 vis[u] = true; // 标记该顶点为已访问过 // 遍历与该顶点相邻的顶点 for (int i = 0; i < G[u].size(); i++) { int v = G[u][i].to; // 相邻顶点的编号 int w = G[u][i].w; // 该边的权值 // 如果当前路径比已有的路径更短,则更新最短距离 if (dis[v] > dis[u] + w) { dis[v] = dis[u] + w; // 更新最短距离 q.push(make_pair(dis[v], v)); // 将更新后的顶点加入到优先队列中 } } } } int main() { int n, m, s; cin >> n >> m >> s; // 读入图的边 for (int i = 0; i < m; i++) { int u, v, w; cin >> u >> v >> w; G[u].push_back(Edge(v, w)); // 添加一条从u到v,权值为w的边 } dijkstra(s); // 进行最短路径计算 // 输出每个顶点到源点的最短距离 for (int i = 1; i <= n; i++) { if (dis[i] == INF) cout << "INF" << endl; else cout << dis[i] << endl; } return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值