POJ 1459--最大流算法

 

cin竟然比scanf慢了十几倍,想不通

#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
#include <cmath>
#include <map>
#include <algorithm>
#include <list>
#include <ctime>
#include <set>
#include <queue>
#include <cstring>
#include <cstdio>
using namespace std;
#define INT_MAX 10000000
#define N 105
#define CLR(arr, what) memset(arr, what, sizeof(arr))
int capacity[N][N]; //容量
int flow[N]; //残余流量
int pre[N]; //前趋
int n; //节点个数

queue<int> Q;

int BFS(int src, int des) {
    //初始化
    while (!Q.empty()) {
        Q.pop();
    }
    for (int i = 1; i < n + 1; i++) {
        pre[i] = -1;
    }
    pre[src] = 0;
    flow[src] = INT_MAX; //初始化源点的流量为无穷大
    Q.push(src);
    while (!Q.empty()) {
        int index = Q.front();
        Q.pop();
        if (index == des) { //找到了增广路径
            break;
        }
        for (int i = 1; i < n + 1; i++) {
            if (i != src && capacity[index][i] > 0 && pre[i] == -1) {
                pre[i] = index;
                //增广路残容流量
                flow[i] = min(capacity[index][i], flow[index]);
                Q.push(i);
            }
        }
    } //while
    if (pre[des] == -1) {
        return -1; //残留图中不存在增广路径
    } else {
        return flow[des];
    }
}

int MaxFlow(int src, int des) {
    int aug = 0;
    int sumflow = 0;
    while ((aug = BFS(src, des)) != -1) {
        int k = des; //利用前驱寻找路径
        while (k != src) {
            int last = pre[k];
            capacity[last][k] -= aug;
            capacity[k][last] += aug;
            k = last;
        }
        sumflow += aug;
    }
    return sumflow;
}
struct node {
    string in, out;
    int cap;
};
int checkin(string & a, string& b) {
    int sz = a.size();
    bool judge = 1;
    for (int i = 0; i < sz; i++) {
        if (a[i] == '2' || b[i] == '2') {
            continue;
        } else if (a[i] != b[i]) {
            judge = 0;
            break;
        }
    }
    if (1 == judge)
        return 1;
    return 0;
}

int cur[N]; //后继
int dis[N]; //距离
int gap[N]; //层结点数(用于间隙优化)
int SAP(int s, int t) //源点、汇点、结点数
        {
    CLR(gap, 0);
    CLR(cur, 0);
    CLR(dis, 0);
    int u = pre[s] = s, maxflow = 0, aug = INT_MAX;
    int v;
    gap[0] = n;
    while (dis[s] < n) {
        bool flag = false;
        for (v = cur[u]; v <= n; ++v) //寻找允许弧
                {
            if (capacity[u][v] > 0 && dis[u] == dis[v] + 1) {
                flag = true;
                break;
            }
        }
        if (flag) //找到允许弧
        {
            pre[v] = u;
            cur[u] = v;
            aug = min(aug, capacity[u][v]);
            u = v;
            if (v == t) //找到完整增广路
                    {
                maxflow += aug;
                for (v = t; v != s; v = pre[v]) //更新残留网络
                        {
                    capacity[pre[v]][v] -= aug; //正向边
                    capacity[v][pre[v]] += aug; //反向边
                }
                aug = INT_MAX;
                u = s; //重新从源点寻找
            }
        } else //找不到允许弧
        {
            int mindis = n;
            for (v = 1; v <= n; ++v) //重新标号
                    {
                if (capacity[u][v] && mindis > dis[v]) {
                    cur[u] = v;
                    mindis = dis[v];
                }
            }
            if (--gap[dis[u]] == 0) //更新断层 + 判断是否断层(间隙优化)
                break;
            gap[dis[u] = mindis + 1]++; //更新断层
            u = pre[u]; //当前弧优化
        }
    }
    return maxflow;
}

inline void addedge(int x, int y, int c) { // add an arc(x -> y, c); vertex: 0 ~ n-1;
    capacity[x][y] = c;
}

int main() {
    int t, np, nc, m, power, id, u, v, cap;
    char tmp;
    while (cin >> t) {
        scanf("%d%d%d", &np, &nc, &m);
        int curn = t + 2;
        n = curn;
        memset(capacity, 0, sizeof(capacity));
        for (int i = 0; i < m; i++) {
            scanf(" (%d,%d)%d ", &u, &v, &cap);
            if (u == v) {
                continue;
            } else {
                u++;
                v++;
                addedge(u, v, cap);
            }
        }
        for (int i = 0; i < np; i++) {
            scanf(" (%d)%d ", &id, &power);
            addedge(0, id + 1, power);
        }
        for (int i = 0; i < nc; i++) {
            int power, id;
            scanf(" (%d)%d ", &id, &power);
            addedge(id + 1, curn - 1, power);
        }
        int sum = MaxFlow(0, curn - 1);
//int sum = SAP( 0, curn - 1);
        cout << sum << endl;
    }
    return 0;
}

 

 

posted on 2013-05-02 21:38  kakamilan  阅读(148)  评论(0编辑  收藏  举报

导航