POJ - 2387 (最短路 SPFA)

输入,n,m,n表示n条路径,m指m个地点

输入n条路径信息a,b,c(a,b指两个相连的地点,c指路径长度)

SPFA 在形式上和广度(宽度)优先搜索非常类似,不同的是bfs中一个点出了队列就不可能重新进入队列,但是SPFA中一个点可能在出队列之后再次被放入队列,也就是一个点改进过其它的点之后,过了一段时间可能本身被改进(重新入队),于是再次用来改进其它的点,这样反复迭代下去

#include <cstdio>
#include <cstring>
#include <string>
#include <set>
#include <cmath>
#include <iostream>
#include <stack>
#include <queue>
#include <map>
#include <vector>
#include <algorithm>
//const long long mod=2147493647;
#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
using namespace std;
#define N 30005
#define inf 0x3f3f3f3f
int vis[N],dis[N];
int head[N];
struct node
{//se[]是一个链表储存点和边的信息
    int u,v,w,next;
}se[N];
int cnt;
void add(int x,int y,int z)
{
//    se[cnt].u=x;
//    se[cnt].v=y;
//    se[cnt].w=z;
//    se[cnt].next=head[x];
    se[cnt]=(node){x,y,z,head[x]};
    head[x]=cnt++;
}
void init()
{
    cnt=0;
    mem(head,-1);
    mem(vis,0);
    mem(dis,inf);
}
void spfa(int s)
{
    queue<int>q;
    q.push(s);
    vis[s]=1;//vis[i]=1表示i点在队列q中,反之不在
    dis[s]=0;//dis[i]表示i点到源点的最短距离
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(int i=head[u];i!=-1;i=se[i].next)
        {
            int v=se[i].v;
            int w=se[i].w;
            if(dis[v]>dis[u]+w)
            {
                dis[v]=dis[u]+w;
                if(!vis[v])
                {
                    q.push(v);
                    vis[v]=1;
                }
            }
        }
    }
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    init();
    for(int i=0;i<n;i++)
    {
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        add(a,b,c);
        add(b,a,c);
    }
    spfa(1);
    printf("%d\n",dis[m]);
}
/*
in
5 5
1 2 20
2 3 30
3 4 20
4 5 20
1 5 100

out
90
*/

猜你喜欢

转载自blog.csdn.net/Kuguotao/article/details/88766905