P1821 [USACO07FEB] Cow Party S
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; }