首页 > 代码库 > SPFA(Bellman-Ford队列优化)
SPFA(Bellman-Ford队列优化)
原理:队列+松弛操作
将源点加入队尾,每一步读取队头顶点u,并将队头顶点u出队(记得消除标记);将与点u相连的所有点v进行松弛操作,如果能更新距离(即令d[v]变小),那么就更新,另外,如果点v没有在队列中(打个标记),那么要将点v入队,如果已经在队列中了,那么就不用入队
以此循环,直到队空为止就完成了单源最短路的求解
判断有无负环:
如果某个点进入队列的次数超过N次则存在负环
/**************************************************************************************************** 最短路—Bellman-Ford算法队列优化(SPFA)邻接表 将边权替换为概率,相加改为相乘,最短距离改为最大概率 ********************************************************************************************************/#include<cstdio>#include<queue> #define maxint 99999999#define maxn 10005#define eps 1e-8using namespace std;struct Edge{ int next,to; double power;}e[maxn*6];//保存边double dist[maxn];// 结点到源点最小距离(最大概率) int ed[maxn];//邻接表 int n,m,source=1,c[maxn];// 结点数,边数,源点,记录进队次数 bool vis[maxn];//判断是否在队列中 queue<int> q;void in(){// 初始化图 scanf("%d%d",&n,&m);// 输入结点数,边数 for(int i=1;i<=n;i++)dist[i]=0;//初始化刚开始距离为最大(概率为最小) dist[source]=1;//到源点最小距离为0(概率为1) int x,j; for(int i=1;i<=m;i++){ j=i<<1; scanf("%d%d%lf",&x,&e[j].to,&e[j].power);e[j].power/=100; e[j].next=ed[x];ed[x]=j; e[j+1].to=x;e[j+1].next=ed[e[j].to];ed[e[j].to]=j+1;e[j+1].power=e[j].power; }}bool SPFA(int s){ q.push(s);vis[s]=1,c[s]=1; while(!q.empty()){ int x=q.front();q.pop();vis[x]=0; int i=ed[x]; while(i){ int j=e[i].to; if(dist[x]*e[i].power-eps>dist[j]){ dist[j]=dist[x]*e[i].power;//松弛 vis[j]=1;//标记 c[j]++;q.push(j);//入队 if(c[j]>n)return 0;//有负环 } i=e[i].next; } } return 1;}int Perseverance(){ freopen("toura.in","r",stdin); freopen("toura.out","w",stdout); in(); if(SPFA(1)) printf("%.6lf",dist[n]*100); return 0;}int comeon=Perseverance();int main(){ return 0;}
SPFA(Bellman-Ford队列优化)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。