//Bellman-Ford算法的队列优化
//有向图 能解决负权 负圈会呈现一定形式,可加入判断,判断是否有负圈
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define MAXN 10000
#define MAXM 1000
#define INF 0X7FFFFFFF
struct node{
int to;
int weight;
int next;
}edge[MAXM];
int head[MAXN+1],cnt;
int n,m;
void Init(){
cnt=0;
memset(edge,0,sizeof(edge));
memset(head,0,sizeof(head));
}
void Add(int x,int y,int z){
cnt++;
edge[cnt].to=y;
edge[cnt].weight=z;
edge[cnt].next=head[x];
head[x]=cnt;
}
void Bellman_Ford(int start){
int *dis=new int[n+1];
int *times=new int[n+1];
int *book=new int[n+1];
int *queue=new int[n*n];
int front=0,tail=0;
for(int i=1;i<=n;i++){
dis[i]=INF;
times[i]=0;
book[i]=0;
}
dis[start]=0;
book[start]=1;
queue[tail++]=start;
//每个点最多入队/出队n-1次
//第一轮,最多经过一条边的最短路径,第二轮,最多经过两条边......第n-1轮,最多经过n-1条边。
// 不可能n条边,否则就有回路了,有回路的路径肯定不是最短的,若回路为正,则明显不为最短。若回路为负,则不存在最短
//用数组存储每个点出队的次数,若到达n,有负圈
while(front<tail){
int t=queue[front++];
book[t]=0;
times[t]++;
if(times[t]>=n){
return;
}
for(int i=head[t];i;i=edge[i].next){
if(edge[i].weight!=INF&&dis[edge[i].to]>dis[t]+edge[i].weight){
dis[edge[i].to]=dis[t]+edge[i].weight;
if(!book[edge[i].to]){
queue[tail++]=edge[i].to;
book[edge[i].to]=1;
}
}
}
}
for(int i=1;i<=n;i++){
printf("%d%c",dis[i],i==n?'\n':' ');
}
}
int main(){
int start,x,y,z;
cin>>n>>m>>start;
for(int i=1;i<=n;i++){
cin>>x>>y>>z;
Add(x,y,z);
}
Bellman_Ford(start);
return 0;
}
无向图:全正可以,有负权结果会很乱,因为在负权那里转圈
Bellman-Ford算法的队列优化
最新推荐文章于 2024-09-27 16:53:40 发布