Til the Cows Come Home (dijsktra堆优化,bellman_ford)

题目链接
以前用朴素dijsktra做过,由于学了几种新算法,用这道题练练
朴素dij版
dij堆优化:
和原理当然是和朴素版的dij差不多,不过由于因为引进了优先队列,可以较快的找出当前点集中到源点举距离最短的点。
ac代码:

#include <iostream>//dijkstra堆优化
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
using namespace std;
#define int long long 
struct node {
	int to, w;
	bool operator < (const node &a) const {//小根堆
		return w > a.w;
	}
}; 
struct nd {
	int to, w;
};
vector<node> l[2005];
priority_queue<node> k;
int dis[2005]; int t, n;
void dij(int s,int o) {
	memset(dis, 0x3f3f3f3f, sizeof(dis));
	dis[s] = 0;
	node p;
	p.to = 1;
	p.w = 0;
	k.push(p);
	while (!k.empty()) {
		int v = k.top().to;
		int val = k.top().w; k.pop();
		if (dis[v] < val) continue;//很重要的一步,表示这个点之前已经经过了松弛才使得距离变短,也意味着该点的该状态已经失去了价值
		for (int i = 0; i < l[v].size(); i++) {
			node g = l[v][i];
			if (val + g.w < dis[g.to]) {//松弛
				dis[g.to] = val + g.w;
				node q;
				q.to = g.to;
				q.w = val + g.w;
				k.push(q);//将被松弛点入队
			}
		}
	}
	cout << dis[o] << endl;
	return;
}
signed main() {
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	cin >> t >> n;
	for (int i = 1; i <= t; i++) {
		int a, b, c; cin >> a >> b >> c;
		node p; p.to = b; p.w = c;
		node q; q.to = a; q.w = c;
		l[a].push_back(p);
		l[b].push_back(q);
	}
	dij(1,n);
}

bellman-ford:
原理也很简单,将dis[1]=0,其余全部初始化为max之后,对所有边进行n-1次松弛操作,暴力地达到一种dij的效果,但因为bellman并没有标记点的操作,每条边都在每一次循环中都进行了松弛的判断,所以不会出现dij中因为点已经在之前被标记而无法通过负权边来松弛。所以bellman可以处理含有负权边的情况。
bellman还可以判断图中是否存在负权环的情况,如果一个图中存在负权环的话肯定是不可能通过松弛操作来得到一个最短路径,因为每一次松弛经过负权边都会使得距离变得更小,而正常情况下经过了Bellman的n-1次循环松弛操作之后图中的距离都会达到最短路径无法被松弛,所以判断一个图是否含有负权环就在bellman后对每一个距离都进行一次松弛如果距离有变化则表示图中含有负权环。
ac代码:

#include <iostream>//bellman_ford
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;
#define int long long
struct node {
	int v,to, w;
};
vector<node> l;
int dis[2005]; int t, n;
void bellman(int s, int e) {
	memset(dis, 0x3f3f3f3f, sizeof(dis));
	dis[s] = 0;
	//bellman_ford核心代码
	for (int i = 1; i <= e - 1; i++) {//松弛
		for (int j = 0; j < l.size(); j++) {//每条边判断
			dis[l[j].to] = min(dis[l[j].to], dis[l[j].v] + l[j].w);
		}
	}
	cout << dis[e] << endl;
}
signed main() {
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	cin >> t >> n;
	for (int i = 1; i <= t; i++) {
		int a, b, c; cin >> a >> b >> c;
		node p, q;
		p.v = a;  p.to = b; p.w = c;
		q.v = b;  q.to = a; q.w = c;
		l.push_back(p); l.push_back(q);
	}
	bellman(1, n);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值