spfa(模板)

    spfa作为图论中的常用算法,深受各类出题人和各位OIer的喜爱;

    so,为了给大众创造福利,宝宝在此奉上spfa大发的思路和模板;以感谢社会,

感谢CCF,感谢CCTV,

感谢我的老师,感谢同学们,

感谢noi,感谢noip,感谢ioi,

感谢不辞辛劳的学长学姐,

感谢帮我改程序,被我烦死的xxy ~QAQ~······and so on;

程序和图解做得比较难看,就请大家见谅了!!~(≧▽≦)/~ 谢啦!!☆⌒(*^-゜)v

思路:见程序

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int v,x,y,n; 
int head[100000],num,m,dis[1000];
bool vis[10000];
struct nond
{
    int pre,v,to,from;
//pre指这条边的上一条边,v指这条边的边权,to指这条边的终点,from至这条边的终点; 
}e[100000];//边表存储,减少空间占用; 
queue<int>q;//队列存储所能更新的点; 
void put(int from,int to,int v)
{
    e[++num].pre=head[from];
    e[num].from=from;//
    e[num].to=to;
    e[num].v=v//;这三句很好理解不解释 
    head[from]=num;
}//边表的读入函数; 
/*重点解释一下对于改变的上一条边的存储,
看程序下的图片详解,在此不进行解释;*/ 
void spfa(int s)
{
    q.push(s);//把s放入队列中; 
    vis[s]=1;//把节点s标记为使用中; 
    int point=s;//用point去更新所有与point相连的节点的最短距离; 
    while(!q.empty())//如果队列不为空,说明有节点能去更新其他节点; 
    {
        point=q.front();//记录队列中的第一个节点去更行其他节点; 
        q.pop();//队列中的第一个节点已被使用,弹出; 
        vis[point]=0;//该节点被弹出了队列,变为未被访问,未被使用; 
        for(int i=head[point];i;i=e[i].pre)//以该节点去更新其他节点 
        {
            if(dis[e[i].from]+e[i].v<dis[e[i].to])//自己理解,不解释 
            {
                dis[e[i].to]=dis[e[i].from]+e[i].v;
                q.push(e[i].to);
                //节点i的最短距被更新过,说明i又可以去更新其他节点,把i读入队列; 
                vis[e[i].to]=1;//标记为使用中; 
            }
        }
    }
}
int main()
{
    cin>>n>>m;//n节点个数,m是边的个数; 
    memset(dis,127/3,sizeof(dis));
    dis[1]=0;//dis存储到第i个点的最短路的长度; 
    for(int i=1;i<=m;i++){
        cin>>x>>y>>v;//x,y,v分别是相连边的起点~终点~长度; 
        put(x,y,v);//向边表里加入边 
        put(y,x,v);//因为是无向图,所以加入两次; 
    }
    spfa(1);//spfa搜索!!!这是重点!注意了~(≧▽≦)/~
    for(int i=1;i<=n;i++)
    cout<<dis[i]<<" ";
}

 

对边表读入的解释

对边表读入的解释

 

 

如果对你有所帮助,别忘了加好评哦;么么哒!!下次见!88

 

posted @ 2016-12-18 10:30  一蓑烟雨任生平  阅读(185)  评论(0编辑  收藏  举报