图的构造
#include <vector>
#include <iostream>
using namespace std;
struct edge{
int to, cost;
};
const int MAX = 1000;
vector<edge> G[MAX]; // 图
int V; // 顶点数
int E; // 边数
void creat(){
// 因为只是支持顶点 0 ~ n, 如果顶点是 1 ~ n, 自行更改 只要把顶点的值减 1 就行了
// 这里假设是 0 ~ n
cin >> V >> E;
for(int i = 0; i < E; ++i){
int from, to, cost;
cin >> from >> to >> cost;
edge e;
e.to = to;
e.cost = cost;
G[from].push_back(e);
}
}
int main(){
creat();
return 0;
}
Dijkstra算法(未经优化)
#include <vector>
#include <iostream>
using namespace std;
struct edge{
int to, cost;
};
const int MAX = 10001;
const int INF = 0x3f3f3f3f; // 假设这是无法到达的话的距离
vector<edge> G[MAX]; // 图
int d[MAX];
int used[MAX];
int V; // 顶点数
int E; // 边数
int s; // 出发的点
void creat(){
// 因为只是支持顶点 0 ~ n, 如果顶点是 1 ~ n, 自行更改 只要把顶点的值减 1 就行了
// 这里假设是 0 ~ n
cin >> V >> E >> s;
for(int i = 0; i < E; ++i){
int from, to, cost;
cin >> from >> to >> cost;
edge e;
e.to = to;
e.cost = cost;
G[from].push_back(e);
}
}
void Dijkstra(int s){
fill(d, d + V, INF);
fill(used, used + V, false);
d[s] = 0;
while(true){
int v = -1;
for(int i = 0; i < V; ++i){
if(!used[i] && (v == -1 || d[v] > d[i])){ // 寻找到达某一点的最短距离
v = i;
}
}
if(v == -1) break;
used[v] = true;
for(int i = 0; i < (int)G[v].size(); ++i){
edge e = G[v][i];
if(d[v] != INF) // 如果存在不能到达的点的话,则不予考虑
d[e.to] = min(d[e.to], d[v] + e.cost); // v -> i 从v到 e.to顶点的距离
}
}
}
void solve(){
creat();
Dijkstra(s);
for(int i = 0; i < V; ++i) cout << d[i] << ' '; // 输出到达各个顶点的最短距离, 如果无法到达结果为 INF
}
int main(){
solve();
return 0;
}
Dijkstra(优先队列的优化)
#include <vector>
#include <iostream>
#include <queue>
#include <utility>
using namespace std;
struct edge{
int to, cost;
};
typedef pair<int, int> P;
const int MAX = 10001;
const int INF = 0x3f3f3f3f; // 假设这是无法到达某一点的距离
vector<edge> G[MAX]; // 图
int d[MAX];
int used[MAX];
int V; // 顶点数
int E; // 边数
int s; // 出发的点
void creat(){
// 因为只是支持顶点 0 ~ n, 如果顶点是 1 ~ n, 自行更改 只要把顶点的值减 1 就行了
// 这里假设是 0 ~ n
cin >> V >> E >> s;
for(int i = 0; i < E; ++i){
int from, to, cost;
cin >> from >> to >> cost;
edge e;
e.to = to;
e.cost = cost;
G[from].push_back(e);
}
}
void Dijkstra(int s){
priority_queue<P, vector<P>, greater<P> > que; // 要空一个格
fill(d, d + V, INF);
que.push(P(0, s));
d[s] = 0;
while(!que.empty()){
P p = que.top(); que.pop();
int v = p.second; // first 储存最短距离 second 储存的是顶点的坐标
if(d[v] < p.first) continue; // 一直寻找,直到找到符合最短距离的 v 点
for(int i = 0; i < (int)G[v].size(); ++i){
edge e = G[v][i]; // v -> e.to 的边
if(d[e.to] > d[v] + e.cost){
d[e.to] = d[v] + e.cost;
que.push(P(d[e.to], e.to));
}
}
}
}
void solve(){
creat();
Dijkstra(s);
for(int i = 0; i < V; ++i) cout << d[i] << ' '; // 输出到达各个顶点的最短距离, 如果无法到达结果为 INF
}
int main(){
solve();
return 0;
}
SPFA
#include <vector>
#include <iostream>
#include <queue>
using namespace std;
struct edge{
int to, cost;
};
const int MAX = 10001;
const int INF = 0x3f3f3f3f; // 假设这是无法到达某一点的距离
vector<edge> G[MAX]; // 图
int visit[MAX]; // 是否访问了
int d[MAX];
int used[MAX];
int V; // 顶点数
int E; // 边数
int s; // 出发的点
void creat(){
// 因为只是支持顶点 0 ~ n, 如果顶点是 1 ~ n, 自行更改 只要把顶点的值减 1 就行了
// 这里假设是 0 ~ n
cin >> V >> E >> s;
for(int i = 0; i < E; ++i){
int from, to, cost;
cin >> from >> to >> cost;
edge e;
e.to = to;
e.cost = cost;
G[from].push_back(e);
}
}
void BFS_Dijkstra(int s){
queue<int> que;
fill(d, d + V, INF);
que.push(s);
d[s] = 0;
while(!que.empty()){
int v = que.front(); que.pop();
visit[v] = 0; // 回溯 回到 v 点, 再继续向其他点扩展
for(int i = 0; i < (int)G[v].size(); ++i){
edge e = G[v][i];
if(d[e.to] > d[v] + e.cost){
d[e.to] = d[v] + e.cost;
if(!visit[e.to]){
visit[e.to] = 1;
que.push(e.to);
}
}
}
}
}
void solve(){
creat();
BFS_Dijkstra(s);
for(int i = 0; i < V; ++i) cout << d[i] << ' '; // 输出到达各个顶点的最短距离, 如果无法到达结果为 INF
}
int main(){
solve();
return 0;
}
Bellman_Ford算法
#include <iostream>
#include <cstring>
using namespace std;
// 边
struct edge{
int from, to, cost;
};
const int INF = 0x3f3f3f3f;
const int V_MAX = 10001; // 顶点的最大数目
const int E_MAX = 10001; // 边的最大数目
int V; // 顶点数 一样是 0 ~ n
int E; // 边数
int s; // 起点
edge es[E_MAX];
int d[V_MAX];
void creat(){ // 构造图, 另一种构建方法
cin >> V >> E >> s;
for(int i = 0; i < E; ++i){
cin >> es[i].from >> es[i].to >> es[i].cost; // from -> to 的边的距离 = cost
}
}
void Bellman_Ford(int s){
fill(d, d + V, INF);
d[s] = 0;
while(true){
bool update = false;
for(int i = 0; i < E; ++i){
edge e = es[i];
if(d[e.from] != INF && d[e.to] > d[e.from] + e.cost){ // 不断寻找到达e.to 的最短距离
d[e.to] = d[e.from] + e.cost;
update = true;
}
}
if(!update) break; // 如果没有最短的路径可寻找了, 退出!
}
}
// 求负圈的算法
// 因为最短路不会经过同一个点两次(也就是说罪过通过 V - 1条边,whlie(true) 最多执行 V - 1次)
// 反之,如果存在从 s 可达的负圈,那么在第 | V |次循环中也会更新 d 的值
bool find_negative_loop(){
memset(d, 0, sizeof(d));
for(int i = 0; i < V; ++i){
for(int j = 0; j < E; ++j){
edge e = es[j];
if(d[e.to] > d[e.from] + e.cost){
d[e.to] = d[e.from] + e.cost;
if(i == V - 1) return false;
}
}
}
return true;
}
void solve(){
creat();
Bellman_Ford(s);
for(int i = 0; i < V; ++i) cout << d[i] << ' '; // 输出最短距离
}
int main(){
solve();
return 0;
}