poj-1273

11 篇文章 0 订阅
// 936K    32MS    G++
#include <cstdio>
#include <cstring>
#include <queue>

#define MAX 210
#define INF 999999

long long intersectionMap[MAX][MAX];

int prev[MAX];
int flow[MAX];

int N;
int M; // intersection num

using namespace std;

queue<int> BFSQueue;
long long minFlow;
char BFSFlag[MAX];

char BFS() {
    // printf("BFS\n");
    memset(prev, 0, sizeof(prev));
    memset(flow, 0, sizeof(flow));
    memset(BFSFlag, 0, sizeof(BFSFlag));
    while(BFSQueue.size()) {
        BFSQueue.pop();
    }

    BFSQueue.push(1); // from s
    prev[1] = 0; // s's prev is 0 which means invalid
    flow[1] = INF;

    BFSFlag[1] = 1;
    minFlow = INF; // record the min flow on this argmenting path
    while(BFSQueue.size()) {
        int curNodeId = BFSQueue.front();
        BFSQueue.pop();
        for (int i = 1; i <= M; i++) { // check the adjacney Node
            if (intersectionMap[curNodeId][i]) { // if has flow > 0
                if (!BFSFlag[i]) {
                    BFSFlag[i] = 1;
                    if (!prev[i]) { // if has not visited
                        prev[i] = curNodeId;
                        minFlow = minFlow < intersectionMap[curNodeId][i] ? 
                                    minFlow : intersectionMap[curNodeId][i];
                        if (i == M) { // if reach t, a path has been found
                            return 1;
                        }
                        BFSQueue.push(i);
                    }
                }
            }
        }
    }

    return 0;
}

int solve() {
    long long maxRate = 0;
    while (BFS()) { // find a augmenting path
        int prevNodeId = prev[M];
        int currentNodeId = M; // check from t to s
        while(prevNodeId) { // adjust the flow of this path
            intersectionMap[prevNodeId][currentNodeId] -= minFlow;
            intersectionMap[currentNodeId][prevNodeId] += minFlow;
            currentNodeId = prevNodeId;
            prevNodeId = prev[currentNodeId];
        }
        maxRate += minFlow;
    }
    // for (int i = 1; i <= M; i++) {
    //     maxRate += intersectionMap[M][i];
    // }
    printf("%lld\n", maxRate);
}


int main() {
    while(scanf("%d %d", &N, &M) != EOF) {
        int beginIntersection;
        int endInteresction;
        long long maxRate;
        memset(intersectionMap, 0, sizeof(intersectionMap));
        for (int i = 0; i < N; i++) {
            scanf("%d %d %lld", &beginIntersection, &endInteresction, &maxRate);
            // intersectionMap[beginIntersection][endInteresction] = 
            // intersectionMap[beginIntersection][endInteresction] > maxRate ? 
            // intersectionMap[beginIntersection][endInteresction]: maxRate;
            intersectionMap[beginIntersection][endInteresction] += maxRate;
        }
        solve();
    }
}

第一道流的题,本来根本不准备涉及流这一块的,因为不但工作中用不到,在现在的面试笔试中也基本没有,从功利性角度出发,

完全没有必要,但是随着最近的刷题,不断的延伸,发现这一块还是避免不了,虽然可能没有什么直接作用,但是没准会有潜移默化的好处。

正好现在也基本能看懂了,就坐坐这些题吧。

这一道应该是流的基本题了,转化难度为0,完全是为了流而流的题,作用就是熟悉和练习Edmonds-Karp算法。

总结一下流程:

算法思路简单,就是用BFS不断的寻找从s到t的增广路,如果找到一条,就对相应的正/反向路径 -/+本次的最大流,

一直到找不到增广路为止,这时候,从s到t的就是最大流。

每次BFS都是从s开始,

在BFS的过程中,有两个额外的关键变量:

一个是本次找到的增广路的所有路径里最小的正向flow值 minFlow,初始为INF。

另外一个是prev数组,来保存此增广路中的每个节点的前驱节点,其实prev[s]在开始置为0,表示没有前驱节点了。

然后在每次BFS检查点curId的周围正向flow大于0(正向flow>0保证了此路是增广路,还可以传输flow)的点集时,除了检查是否BFS过以外,还要检查该点k在不在已经遍历过的路中(及其前驱prev[k]还没有被设置),不在才将此节点k加入到路径中去,如果k是终点t的话,直接返回1表示有增广路存在,如果不是,那么将新加入的这段路的正向flow

和minFlow比较,minFlow取两者最小的。

在找到了一条增广路以后,就根据前驱prev从t反向到s处理每一段路径的正向flow(-minFlow)和反向flow(+minFlow),同时最大流 S(初始为0)+= minFlow.

最后输出minFlow即可。

要注意本题似乎会有重边,eg:

1 2 5

1 2 7

1 2 8

总共3个,都是从1到2的flow,在处理时,要累加起来,等价于最后的 1 2 20.

反向flow存在意义还要研究研究.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值