1.普通版dijstra写法:
#include<bits/stdc++.h>
using namespace std;
const int inf = 1e8+10; // 定义无穷大值,表示不可达
int ma[1005][1005]; // 邻接矩阵存储图结构
int vis[1005]; // 标记数组,记录节点是否已访问
int dis[1005], way[1005]; // dis存储单源最短距离,way存储去程距离
int n, m, x; // n-节点数,m-边数,x-目标农场编号
// Dijkstra算法实现
void dijstra(int sx) {
int pos = 1, minn, sum = 0;
memset(vis, 0, sizeof(vis)); // 初始化访问标记
// 初始化距离数组:从sx到各点的初始距离
for(int i = 1; i <= n; i++)
dis[i] = ma[sx][i];
vis[sx] = 1; // 标记起点已访问
dis[sx] = 0; // 起点到自身距离为0
// 主循环,每次找出一个最近节点
for(int i = 1; i <= n; i++) {
minn = inf;
// 找出当前未访问的最近节点
for(int j = 1; j <= n; j++) {
if(vis[j] == 0 && minn > dis[j]) {
minn = dis[j];
pos = j;
}
}
if(minn == inf) break; // 剩余节点不可达则退出
vis[pos] = 1; // 标记该节点已访问
// 松弛操作:更新相邻节点距离
for(int j = 1; j <= n; j++) {
if(vis[j] == 0 && dis[j] > minn + ma[pos][j]) {
dis[j] = minn + ma[pos][j];
}
}
}
}
int main() {
cin >> n >> m >> x;
// 初始化邻接矩阵
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++) {
if(i == j) ma[i][j] = 0; // 对角线为0
else ma[i][j] = inf; // 初始设为无穷大
}
// 读入边信息
for(int i = 1; i <= m; i++) {
int a, b, c;
cin >> a >> b >> c;
if(ma[a][b] > c) // 保留最短边
ma[a][b] = c;
}
// 第一次Dijkstra:计算各点到x的最短距离(回程)
dijstra(x);
for(int i = 1; i <= n; i++)
way[i] = dis[i]; // 保存回程距离
// 转置邻接矩阵:将边反向,用于计算x到各点的距离(去程)
for(int i = 1; i <= n; i++)
for(int j = i + 1; j <= n; j++) {
swap(ma[i][j], ma[j][i]);
}
// 第二次Dijkstra:计算x到各点的最短距离(去程)
dijstra(x);
// 找出最大的往返距离
int ans = -1;
for(int i = 1; i <= n; i++) {
ans = max(way[i] + dis[i], ans);
}
cout << ans;
return 0;
}
2.优先队列优化的dijkstra版
3. Floyd版