Bellman_ford + SPFA

1,Bellmanford(最短路,判断负环);

  • 为了求解边上带有负权值的单源最短路径
  • 同时还可以判断是否存在权值为负数的回路,如果存在,(就没有最短路了)
  • 反复利用已经有的边来更新最短距离,核心在松弛:dis[u] + mp[u][v] < dis[v] ,那么 dis[v] = dis[u] + mp[u][v],反复松弛之后 (一次松弛表明两点之间有了更短的路径), 如果没有负边权回路, n-1次后会结束,每一次迭代所有边后,找到了经过k条边的最短路(这只是暂时的最短路),有n个点,所以n-1次后才能完全找出最短路
  • 对于负权值回路,是不可能有最短路径的,比如A,B,C,D四个点,A,B形成了负回路,如果起点是A,那么dis[A] 肯定是负数,这样就会一直进行下去
//一共n条边
struct node{//表示每条边s->e:v
	int s, e, v;
	node(int a, int b, int c){
		s = a, e = b, v = c;
	} 
};
vector<node> g;
int dis[N];//起点U到各点的距离,初始化为无穷

bool bellman_ford(int u){//起点u
	memset(dis, 0x3f3f3f3f, sizeof(dis));
	dis[u] = 0;
	//n-1次操作
	bool flag;
	forint i = 1; i <= n; i++{
		flag = false;//一次扫描所有边都没有松弛,下一次照样不会 可以提前结束循环
		for(int j = 0; j < g.size(); j++){
			int s = g[j].s;
			int e = g[j].e;
			int v = g[j].v;
			if(dis[e] > dis[s] + v){
				dis[e] = dis[s] + v;
				flag = true;
			}
		}
		if(!flag) return false; //不存在负环
	}
	return flag;
}

2,SPFA(bellman_ford的优化)

struct node{
	int  e, v;//邻接矩阵 edge[s] s->e : v
	node( int b, int c){
		e = b, v = c;
	} 
};
const int inf = 0x3f3f3f3f;
vector<node> edge[1000];
int n; 
int dis[1000];
int num[1000];//用来记录松弛次数
bool vis[1000];//标记是否在队列
bool SPAF(){
	memset(num, 0, sizeof(num));
	memset(vis, false, sizeof(vis)); 
	memset(dis, inf, sizeof(dis));
	dis[1] = 0;
	vis[1] = true;
//	num[1] ++;
	queue<int> Q;
	Q.push(1);
	while(!Q.empty()){
		int u = Q.front();//起点入队
		Q.pop();
		vis[u] = false;
		for(int i = 0; i < edge[u].size(); i++){
			int e = edge[u][i].e;
			int v = edge[u][i].v;
			if(dis[e] > dis[u] + v){
				dis[e] = dis[u] + v;
				if(!vis[e]){//队列没有这个点入队
					Q.push(e);
					vis[e] = true;
					num[e] ++;//这个点被松弛了一次
					if(num[e] > n) return true;//根据bellman_ford,一共迭代n次,每个点许多被松弛n次 所以当超过n次就会一直松弛下去,即存在负环; 
				}
			}
		}
	} 
	return false;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值