其他分享
首页 > 其他分享> > 最短路模板(堆优化dijstra + spfa)

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

作者:互联网

/**\
最短路模板
输入: 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