poj1511 最短路 spfa

本文详细介绍SPFA算法原理及其实现方式,通过一个具体的POJ1511题目示例,展示了如何使用队列优化的Bellman-Ford算法解决最短路径问题,并附带完整的C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

//    poj1511 最短路 spfa
//
//    Bellman-Ford 队列优化
//
//    留个spfa模板,精髓就是不断松弛,并将可能会影响
//    结果的点,如果在队列中不用加,不在就加入。



#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <queue>

typedef long long ll;

using namespace std;

const int MAX_N = 1000009;
const int INF = 0x7f7f7f7f;
//typedef pair<int,int> P;

int head[MAX_N];
int num;
int n,m;
bool inq[MAX_N];
ll d[MAX_N];
int cnt[MAX_N];

struct edge{
    int from;
    int to;
    int w;

    edge(){}

    edge(int from,int to,int w):from(from),to(to),w(w){}
};

edge eg[MAX_N];

struct node {
    int to;
    int w;
    int next;

    node(){

    }

    node(int to,int w,int next):to(to),w(w),next(next){

    }

};

node edges[MAX_N];

queue<int> que;

void add_edge(int u,int v,int cost){
    edges[num] = node(v,cost,head[u]);
    head[u] = num++;
}

void input(){
    scanf("%d%d",&n,&m);
    int u,v,w;
    for (int i=1;i<=m;i++){
        scanf("%d%d%d",&u,&v,&w);
        eg[i] = edge(u,v,w);
    }
}

void graph(){
    memset(head,-1,sizeof(head));
    num = 0;
    for (int i=1;i<=m;i++){
        add_edge(eg[i].from,eg[i].to,eg[i].w);
    }
}

void reverser(){
    for (int i=1;i<=m;i++){
        swap(eg[i].from,eg[i].to);
    }
}

ll spfa(int s){
    memset(inq,0,sizeof(inq));
    for (int i=1;i<=n;i++)
        d[i] = INF;
    memset(cnt,0,sizeof(cnt));
    d[s] = 0;
    que.push(s);
    cnt[s]++;
    inq[s] = true;
    while(!que.empty()){
        int  u = que.front();
        que.pop();

        for (int j = head[u];j!=-1;j=edges[j].next){
            int v = edges[j].to;
            int w = edges[j].w;
            if (d[u] != INF && d[v] > d[u] + w){
                d[v] = d[u] + w;
                if (!inq[v]){
                    que.push(v);
                    cnt[v]++;
                    if (cnt[v]>=n){
                        return -1;
                    }
                    inq[v] = true;
                }
            }
        }
        inq[u] = false;
    }
    ll res = 0;
    for (int i=1;i<=n;i++){
        res += d[i];
    }
    return res;
}

void solve(){
    graph();
    ll cost = spfa(1);

    reverser();
    graph();
    cost += spfa(1);
    printf("%lld\n",cost);
}


int main(){
    int t;
    //freopen("1.txt","r",stdin);
    scanf("%d",&t);
    while(t--){
        input();
        solve();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值