spfa

来源:互联网 发布:跳跃网络ceo吴亚西 编辑:程序博客网 时间:2024/06/08 15:28

spfa是一个求解最短路的算法

思路:按类似bfs的顺序进行松弛

   定义一个队列q,以及一个数组vis[]记录每个节点是否在q中

   每次有点出入队时修改vis[],确保能判断每个点是否在q中

   先将起点s入队

   然后开始循环操作,队空为停止条件

        q出队一个点,记做v,将v的所有邻点松弛,对于可以松弛的点,若它不在q中就将其入队。


判断负权回路:若有某点已经入队n次,且还要入第n+1次,则有负权回路


/*有向图的spfa输入: 节点数 边数     边起点 边终点 边权重(*重复边数次)    起点  终点*/#include <bits/stdc++.h>using namespace std;int v,e,s,t;const int maxv=300;vector< pair<int,int> > ve[maxv];int vis[maxv],fa[maxv],d[maxv],coun[maxv];const int maxn=200000;void init(){    memset(ve,0,sizeof(ve));    memset(vis,0,sizeof(vis));    memset(fa,0,sizeof(fa));    memset(coun,0,sizeof(coun));    for(int i=1;i<=v;i++)    {        d[i]=maxn;        fa[i]=i;    }    int cs,ce,cw;    for(int i=1;i<=e;i++)    {        cin>>cs>>ce>>cw;        ve[cs].push_back( make_pair(ce,cw) );        //ve[ce].push_back( make_pair(cs,cw) );    }    cin>>s>>t;     d[s]=0;    coun[s]=1;}bool spfa(){    queue<int> q;    q.push(s);    vis[s]=1;//vis[i]为正1代表他在q内    while(!q.empty())    {       int u=q.front();       q.pop();       vis[u]=0;       for(int i=0;i<ve[u].size();i++)       {           int cv=ve[u][i].first,cw=ve[u][i].second;           if(cw+d[u]<d[cv])           {               d[cv]=cw+d[u];               fa[cv]=u;               if(vis[cv]==0)               {                   vis[cv]=1;                   if(coun[cv]>=v)return false;                    coun[cv]++;                    q.push(cv);               }           }       }    }return true;}int main(){    while(cin>>v>>e,v!=0)    {        init();        if(spfa())           cout<<d[t]<<endl;        else cout<<"-1"<<endl;    }    return 0;}


原创粉丝点击