// http://poj.org/problem?id=1797 Dijkstra 单源单条路径的最大流
Dijkstra
#include <string>
#include <iostream>
#include <vector>
#include <cstdio>
#include <queue>
#include <map>
#include <algorithm>
#include <stack>
#include <cstring>
using namespace std;
#define M(a, b) memset(a,b,sizeof(a))
const int INF = 0x3f3f3f3f;
typedef long long LL;
const int maxn = 1004;
#define typec int
bool vis[maxn]; // bfs遍历过程,划分已访问过的顶点和未访问过的顶点
int pre[maxn]; // 记录最小权重路径, pre[beg] =-1
int cost[maxn][maxn];
int lowcost[maxn];
/**
* 单源最短路,权值必须非负
* 算法复杂度 O(n^2)
* 从 n 个顶点组成的图中,查找从 beg 顶点开始的到各个顶点的最小权重路径的最小权重,顶点编号 1...n
* @param cost 权重, 邻接矩阵 cost[i][j] = 3
* @param lowcost lowcost[i] 待求的到顶点i的最小权重
* @param n 顶点个数
* @param beg 开始节点
*/
void dijkstra(typec cost[][maxn], typec lowcost[], int n, int beg) {
for (int i = 1; i <= n; i++) {
lowcost[i] = INF;
vis[i] = false;
pre[i] = -1;
}
lowcost[beg] = 0;
for (int j = 1; j <= n; j++) { //for循环 40到 57 行
int k = -1;
int t_min = INF;
for (int i = 1; i <= n; i++) {
if (!vis[i] && lowcost[i] <
t_min) { // !vis[i] 从没有遍历过的点中找出可以到达的lowcost 最小的点 ,入口第一步 即为 k = beg 点, 因为 第30行初始化了 lowcost[beg] = 0
t_min = lowcost[i];
k = i;
}
}
if (k == -1) break;
vis[k] = true; // vis[beg] = true,即 beg 点已经访问过
for (int i = 1; i <= n; i++) {
if (!vis[i] && lowcost[k] + cost[k][i] < lowcost[i]) {
lowcost[i] = lowcost[k] + cost[k][i];
pre[i] = k;// 记录本次bfs 一圈的路径
}
}
}
}
/**
* 单源最短路,权值必须非负
* 算法复杂度 O(n^2)
* 从 n 个顶点组成的图中,查找从 beg 顶点开始的到各个顶点的最小权重路径的最小权重,顶点编号 1...n
* @param cost 权重, 邻接矩阵 cost[i][j] = 3
* @param lowcost lowcost[i] 待求的到顶点i的最小权重
* @param n 顶点个数
* @param beg 开始节点
*/
void dijkstra2(typec cost[][maxn], typec lowcost[], int n, int beg) {
for (int i = 1; i <= n; i++) {
lowcost[i] = cost[1][i]; // cost 数组初始化为0,有边的话cost[1][i]则为权值
vis[i] = false;
pre[i] = -1;
}
// lowcost[beg] = 0;
for (int j = 1; j <= n; j++) { // 31到 48 行
int k = -1;
int t_max = 0;
for (int i = 1; i <= n; i++) {
if (!vis[i] && lowcost[i] >
t_max) { // 选择以源点为起点,边权值最大的另一端端点,记录该端点为k
t_max = lowcost[i];
k = i;
}
}
if (k == -1) break;
vis[k] = true; // vis[beg] = true,即 beg 点已经访问过
for (int i = 1; i <= n; i++) {
lowcost[i] = max(lowcost[i], min(lowcost[k], cost[k][i])); // 这里 选取各条路径中流量的最大值来作为该路径的lowcost[i]
// if (!vis[i] && lowcost[k] + cost[k][i] < lowcost[i]) {
// lowcost[i] = lowcost[k] + cost[k][i];
// pre[i] = k;// 记录本次bfs 一圈的路径
// }
}
}
}
void dijkstra3(int n, int beg) {
for (int i = 1; i <= n; i++) {
lowcost[i] = cost[1][i]; // cost 数组初始化为0,有边的话cost[1][i]则为权值
vis[i] = false;
pre[i] = -1;
}
// lowcost[beg] = 0;
for (int j = 1; j <= n; j++) { // 31到 48 行
int k = -1;
int t_max = 0;
for (int i = 1; i <= n; i++) {
if (!vis[i] && lowcost[i] >
t_max) { // !vis[i] 从没有遍历过的点中找出可以到达的lowcost 最小的点 ,入口第一步 即为 k = beg 点, 因为 第30行初始化了 lowcost[beg] = 0
t_max = lowcost[i];
k = i;
}
}
if (k == -1) break;
vis[k] = true; // vis[beg] = true,即 beg 点已经访问过
for (int i = 1; i <= n; i++) {
lowcost[i] = max(lowcost[i], min(lowcost[k], cost[k][i]));
// if (!vis[i] && lowcost[k] + cost[k][i] < lowcost[i]) {
// lowcost[i] = lowcost[k] + cost[k][i];
// pre[i] = k;// 记录本次bfs 一圈的路径
// }
}
}
}
int main() {
std::ios::sync_with_stdio(false);
int T, N, M;
// scanf("%d", &T);
cin>>T;
int ca = 1;
while (ca <= T) {
// scanf("%d %d", &N, &M);
cin>>N>>M;
M(cost, 0);
int v, l_v;
int w;
for (int i = 1; i <= M; i++) {
// scanf("%d%d%d", &v, &l_v, &w);
cin >> v >> l_v >> w;
cost[v][l_v] = w;
cost[l_v][v] = w;
}
// dijkstra3(N, 1);
dijkstra2(cost,lowcost,N,1);
int ans = lowcost[N];
printf("Scenario #%d:\n", ca);
printf("%d\n\n", ans);
ca++;
}
return 0;
}
Heavy Transportation(最短路变形)单源单条路径的最大流
最新推荐文章于 2021-07-24 15:53:40 发布