zoukankan      html  css  js  c++  java
  • SPFA算法

    很多时候给定的图存在负权边,但是Dijkstra算法无能为力,而Bellman-Ford算法的复杂度有过高,

    所以就要用到这篇博客讲述的算法——SPFA算法

    众所周知 Bellman -Ford 算法会对每条边进行 n - 1 次检查,但是在这些检查过程中,有许多检查是没有必要的.事实上,

    唯一应该检查的边存在一个特点:这些边的起点在上一次处理时到源点的距离发生了变化,即松弛成功的边的终点.既然如此,

    那么就可以对算法进行优化,即每遍只处理特殊的点,这些点是上一次在松弛过程中某条边的终点.

    设立一个先进先出的队列来维护这些待处理的点,优化时每次取出队首节点 u, 并且对所有从点 u 出发的边进行松弛操作,对于每条边的终点 v,

    如果以点 v 为终点的边松弛成功, 且 v 不在队列内, 就将点 v 加入队尾.这样不断从对列取出节点来进行松弛操作,

    直至队列空为止.这个算法保证只要最短路径存在, SPFA 必定能求出最小值.

    有向图

    该图片为代码输入的值

    #include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long LL;
    const int INF = 0x3f3f3f3f;
    const int maxn = 100005;
    int head[maxn];
    int dist[maxn];
    struct node {// 用链式前向星存图
        int to;
        int w;
        int next;
    }edge[maxn];
    
    bool SPFA(int s, int n) {//s表示源点,n表示有几个点
        int i ,j ,k;
        bool visit[maxn];
        int outqu[maxn] = {0};//进队的次数
        queue<int>qu;
        for(i = 0; i <= n; i++) {dist[i] = INF;visit[i] = {false};}//到源点的距离,是否在对内,false表示不在队内
        qu.push(s);
        visit[s] = true;//在队内
        dist[s] = 0;
        while(!qu.empty()) {
            int temp = qu.front();
            qu.pop();
            visit[temp] = false;
            outqu[temp]++;
            if(outqu[temp] > n) return false;//存在负环
            for(k = head[temp]; k != -1; k = edge[k].next) {
                if(dist[temp]!= INF && dist[edge[k].to] > dist[temp] + edge[k].w) {//进行松弛操作
                    dist[edge[k].to] = dist[temp] + edge[k].w;
                    if(!visit[edge[k].to]) {//所指向的点不在队内,则将该点放到队尾
                        qu.push(edge[k].to);
                        visit[edge[k].to] = true;
                    }
                }
            }
        }
        return true;
    }
    int main() {
        freopen("in.txt","r",stdin);
        //freopen("out.txt","w",stdout);
        int n, m, w, i, j;
        memset(head, -1, sizeof(head));
        cin >> n >> m;//n代表点的个数,m代表边数
        for(int k = 1; k <= m; k++) {//链式前向星储存
            cin >> i >> j >> w;//i-》j的权值为w
            edge[k].to = j;
            edge[k].w = w;
            edge[k].next = head[i];
            head[i] = k;
        }
        if(SPFA(1,n)) {
            cout << dist[2] << endl;
        }
        else 
            cout << "error" << endl;
        return 0;
    }
  • 相关阅读:
    第一个VS2015 Xaramin Android项目(续)
    第一个VS2015 Xaramin Android项目
    Android SDK Manager 无法打开
    VS 2015 Android 环境设置
    Unity 游戏运行越久加载越慢
    一不注意,在Unity3D中DllImport 引起的Bug.
    Animation显示ListView的每一条记录
    ViewFlipper
    BitmapFactory.Options对图片进行缩放
    显示倒计时的Button按钮
  • 原文地址:https://www.cnblogs.com/creativepower/p/6665412.html
Copyright © 2011-2022 走看看