单源最短路的建图方式 , 1129. 热浪,模板题
德克萨斯纯朴的民众们这个夏天正在遭受巨大的热浪!!!
他们的德克萨斯长角牛吃起来不错,可是它们并不是很擅长生产富含奶油的乳制品。
农夫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;
}