ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

最短路模板(堆优化dijstra + spfa)

2022-03-04 11:31:37  阅读:158  来源: 互联网

标签:q1 now int dijstra vis spfa define 模板 dis


/**\
最短路模板
输入: n m s t 接下来m行 u, v, w表示u -> v 有一条权值为w的无向边
input:
3 3 1 2
1 2 3
2 3 4
1 3 5
output:
3
\**/
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define go continue
#define int long long
#define PII pair<int, int>
#define sf(x) scanf("%lld",&x)
#define ytz int _; sf(_); while(_--)
#define fory(i,a,b) for(int i = a; i <= b; ++i)
#define forl(i,a,b) for(int i = a; i >= b; --i)
#define debug(a) cout << #a << " = " << a <<endl;
const int N = 1e5 + 10;
struct node
{
    int to, w, next;
} e[N << 1];
int cnt = 0, head[N];
inline void add_edge(int u, int v, int w)
{
    e[++cnt].to = v;
    e[cnt].w = w;
    e[cnt].next = head[u];
    head[u] = cnt;
}
inline void init()
{
    cnt = 0;
    memset(head, -1, sizeof head);
}
int n, m, s, t;
struct v
{
    int x, dis;
    bool operator < (const v& a) const
    {
        return dis > a.dis; //stl默认大顶堆
    }
};
int dis[N];
bool vis[N];
/**\
dijstra
1、从源点开始每次选取一个离点集距离最近的点t 添加到集合中
2、利用t点对集合中的点进行松弛操作,进行更新
3、使用堆进行1找点的操作降低时间复杂度
4、不能在有负边权的图中使用
\**/
inline void dijstra(int s, int t)
{
    priority_queue<v> q;
    memset(dis, 0x3f, sizeof dis);
    memset(vis, 0, sizeof vis);
    dis[s] = 0;
    q.push({s, 0});
    while(!q.empty())
    {
        v now = q.top();
        q.pop();
        if(vis[now.x]) go;
        vis[now.x] = 1;
        for(int i = head[now.x] ; i != -1; i = e[i].next)
        {
            int y = e[i].to;
            if(vis[y]) go;
            if(dis[y] > dis[now.x] + e[i].w)
            {
                dis[y] = dis[now.x] + e[i].w;
                q.push({y, dis[y]});
            }
        }
    }
    if(dis[t] > 0x3f3f3f3f) cout << -1;
    else cout << dis[t];
}
/**\
spfa算法思路:
1、每次迭代,取出队头点v,依次枚举从v出发的边,v->u,设边的长度为w
判断dis[v] + w 是否小于dis[u], 小于则更新值,
2、由于s-u的距离变短了,有可能u能改变其他点,使用vis数组判断是否在队列,没有则放入
3、若一个点的入队次数超过n,则存在负环
\**/
queue<int> q1;
inline void spfa(int s, int t)
{
    memset(dis, 0x3f, sizeof dis);
    memset(vis, 0, sizeof vis);
    dis[s] = 0;
    vis[s] = 1;
    q1.push(s);
    while(!q1.empty())
    {
        int x = q1.front();
        q1.pop();
        vis[x] = 0;
        for(int i = head[x]; i != -1; i = e[i].next)
        {
            int y = e[i].to;
            if(dis[y] > dis[x] + e[i].w)
            {
                dis[y] = dis[x] + e[i].w;
                if(!vis[y])
                {
                    q1.push(y);
                    vis[y] = 1;
                }
            }
        }
    }
    if(dis[t] >= 0x3f3f3f3f) cout << -1;
    else cout << dis[t];
}
inline void solve()
{
    init();
    sf(n), sf(m), sf(s), sf(t);
    fory(i, 1, m)
    {
        int x, y, z;
        sf(x), sf(y), sf(z);
        add_edge(x, y, z);
        add_edge(y, x, z);
    }
    //dijstra(s, t);
    spfa(s, t);
}
signed main()
{
    solve();
    return 0;
}

 

标签:q1,now,int,dijstra,vis,spfa,define,模板,dis
来源: https://www.cnblogs.com/-ytz/p/15963572.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有