spfa算法模板

在网上找了些spfa代码,大多数给了我冗杂的感觉。看了其思想后我照着写了一个,保存一下方便以后寻找不足并改进。
spfa是bellman-ford的改进,bellman-ford的想法是把每个边都松弛一下,算法复杂度是V^2,大部分的时间浪费在了查找新的点s和更新当前点的最短距离d。我对于spfa的理解就是bfs或dfs的变形。先用邻接表保存某个点的相邻点(节点参数 : 节点编号,两点距离),这部分复杂度为o(E),然后用队列保存被松弛的相邻节点。
如果某个点进入队列V次,说明图中存在负权回路
代码:
bfs法 这个是有向图

#define N 500
#define INF 0x3f3f3f3f
#define mem(arr,num) memset(arr,num,sizeof(arr))
/***************************************/


int V, E;
struct edge{
    int v, w;
};
int d[N];
int num[N];
bool used[N];
vector  e[N];
bool spfa(int s){
    fill(d, d + V + 1, INF);
    mem(used, 0);
    d[s] = 0;
    num[s] = 1;
    queue <int> que;
    que.push(s);
    while (!que.empty()){
        int x = que.front(); que.pop();
        for (int i = 0; i < e[x].size(); i++){
            int next = e[x][i].v;
            if (d[next]>d[x] + e[x][i].w)
            {
                d[next] = e[x][i].w + d[x];
                if (!used[next])
                {
                    num[next]++;
                    used[next] = true;
                    que.push(next);
                }
                if (num[next] == V)
                    return false;
            }
        }
        used[x] = false;
    }
    return true;
}
int main()
{
    cin >> V >> E;
    for (int i = 1; i <= E; i++){
        int u; edge ed;
        cin >> u;
        cin >> ed.v >> ed.w;
        e[u].push_back(ed);
    }
    if (spfa(1)){
        cout << d[3] << endl;
    }
    else cout << "NO" << endl;
}

然后是dfs类似的 dfs判断负权回路快

#define N 500
#define INF 0x3f3f3f3f
/***************************************/


int V, E;
struct edge{
    int v, w;
};
int d[N];
int num[N];
vector  e[N];
bool spfa(int s){
    for (int i = 0; i < e[s].size(); i++){
        int v = e[s][i].v;
        if (d[v]>d[s] + e[s][i].w){
            d[v] = d[s] + e[s][i].w;
            num[v]++;
            if (num[v] == V)
                return true;
        }
        if (spfa(v)){
            return true;
        }
    }
    return false;
}
int main()
{
    cin >> V >> E;
    for (int i = 1; i <= E; i++){
        int u; edge ed;
        cin >> u ;
        cin >> ed.v >> ed.w;
        e[u].push_back(ed);
    }
    fill(d, d + V + 1, INF);
    d[1] = 0;
    num[1] = 1;
    if (!spfa(1)){
        cout << d[3] << endl;
    }
    else cout << "NO" << endl;
}

如果有什么代码什么问题错误希望大家能够提出来,共同进步

你可能感兴趣的:(最短路)