Heavy Transportation(最短路变形)单源单条路径的最大流

// 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值