单源最短路的建图方式 , 1129. 热浪,模板题

1129. 热浪 - AcWing题库

德克萨斯纯朴的民众们这个夏天正在遭受巨大的热浪!!!

他们的德克萨斯长角牛吃起来不错,可是它们并不是很擅长生产富含奶油的乳制品。

农夫John此时身先士卒地承担起向德克萨斯运送大量的营养冰凉的牛奶的重任,以减轻德克萨斯人忍受酷暑的痛苦。

John已经研究过可以把牛奶从威斯康星运送到德克萨斯州的路线。

这些路线包括起始点和终点一共有 T 个城镇,为了方便标号为 1 到 T。

除了起点和终点外的每个城镇都由 双向道路 连向至少两个其它的城镇。

每条道路有一个通过费用(包括油费,过路费等等)。

给定一个地图,包含 C 条直接连接 2 个城镇的道路。

每条道路由道路的起点 Rs,终点 Re 和花费 Ci 组成。

求从起始的城镇 Ts 到终点的城镇 Te 最小的总费用。

输入格式

第一行: 4 个由空格隔开的整数: T,C,Ts,Te;

第 2 到第 C+1 行: 第 i+1 行描述第 i 条道路,包含 3 个由空格隔开的整数: Rs,Re,Ci。

输出格式

一个单独的整数表示从 Ts 到 Te 的最小总费用。

数据保证至少存在一条道路。

数据范围

1≤T≤2500
1≤C≤6200
1≤Ts,Te,Rs,Re≤T1
1≤Ci≤1000

输入样例:
7 11 5 4
2 4 2
1 4 3
7 2 2
3 4 3
5 7 5
7 3 3
6 1 1
6 3 4
2 4 3
5 6 3
7 2 1
输出样例:
7

 解析:

最短路模板题

spfa代码:更新原则:更新被更新过的点(因为被更新过的点它的值发生了改变)

平均时间复杂度O(M),最坏时间复杂度O(NM)

#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<math.h>
#include<map>
using namespace std;
typedef long long LL;
const int N = 2505, M = 6200 * 2 + 5;
int T, C, S, E;
int h[N], e[M], w[M], ne[M], idx;
int d[N], q[N];
bool st[N];

void add(int a, int b, int c) {
	e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}

void spfa() {
	memset(d, 0x3f3f3f3f, sizeof d);
	int hh = 0, tt = 1;
	q[0] = S, st[S] = 1;
	d[S] = 0;
	while (hh != tt) {
		int t = q[hh++];
		if (hh == N)hh = 0;
		st[t] = 0;
		for (int i = h[t];~i;i= ne[i]) {
			int j = e[i], dd = w[i];
			if (d[j] > d[t] + dd) {
				d[j] = d[t] + dd;
				if(!st[j]){
					q[tt++] = j;
					if (tt == N)tt = 0;
					st[j] = 1;
				}
			}
		}
	}
}

int main() {
	cin >> T >> C >> S >> E;
	memset(h, -1, sizeof h);
	for (int i = 1,a,b,c; i <= C; i++) {
		scanf("%d%d%d", &a, &b, &c);
		add(a, b, c), add(b, a, c);
	}
	spfa();
	cout << d[E] << endl;
	return 0;
}

优化版Dijkstra:更新原则:更新从没被跟新过的点,之前更新过的不在更新,直接跳过(用当前最小的边去更新大的边)时间复杂度 O(mlogn)

#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<math.h>
#include<map>
using namespace std;
typedef long long LL;
const int N = 2505, M = 6200 * 2 + 5;
int T, C, S, E;
int h[N], e[M], w[M], ne[M], idx;
int d[N];
bool v[N];
typedef struct PII{
    int first,second;
}PII;
 
void add(int a, int b, int c) {
	e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}
 
bool operator >(const PII& a, const PII& b) {
	return a.second > b.second;
}
 
void Dijkstra() {
	memset(d, 0x3f3f3f3f, sizeof(d));
	d[S] = 0;
	priority_queue<PII, vector<PII>, greater<PII>>q;
	q.push({ S,0 });
	while (!q.empty()) {
		int t1 = q.top().first;
		int t2 = q.top().second;
		q.pop();
		if (v[t1])continue;
		v[t1]=1;
		//cout << t1 << " ";
		for (int i = h[t1]; ~i; i = ne[i]) {
			int j = e[i],p=w[i];
			if (d[j] > d[t1] + p) {
				d[j] = d[t1] + p;
				q.push({j, d[j]});
			}
		}
	}
	//cout << endl;
}
 
int main() {
	cin >> T >> C >> S >> E;
	memset(h, -1, sizeof h);
	for (int i = 1,a,b,c; i <= C; i++) {
		scanf("%d%d%d", &a, &b, &c);
		add(a, b, c), add(b, a, c);
	}
	Dijkstra();
	cout << d[E] << endl;
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值