poj 1459 Power Network SAP

20 篇文章 0 订阅
1 篇文章 0 订阅

SAP的模板题,主要是输入有点难处理,看有人用sscanf函数处理的,我是直接对字符串进行处理的。

对于SAP:其实核心思想就是高度函数,把它搞懂SAP其实和EK算法本质上是一样的。

还有一个重要的是GAP优化,即当高度出现断层时算法结束。


#include<stdio.h>
#include<string.h>

const int N = 128;
const int INF = 0x3f3f3f3f;

struct Edge {
    int v, next;
    int c;
};
Edge edge[N*N<<2];
int h[N], numh[N], pre[N], curEdge[N];
int n, np, nc, m, cnt;
int fir[N];

void init() {
    cnt = 0;
    memset(fir, -1, sizeof(fir));
}

void addEdge(int u, int v, int c) {
    edge[cnt].v = v;
    edge[cnt].c = c;
    edge[cnt].next = fir[u];
    fir[u] = cnt++;
}

int SAP(int s, int e) {
    memset(h, 0, sizeof(h));
    memset(numh, 0, sizeof(numh));
    memset(pre, -1, sizeof(pre));
    for(int i = 0; i < n; i++)
        curEdge[i] = fir[i];
    numh[0] = n;
    int i;
    int cur = s, pos, mmin, maxflow = 0;
    while(h[s] < n) {
        if(cur == e) {
            mmin = INF;
            for(i = s; i != e; i = edge[curEdge[i]].v) {
                if(mmin > edge[curEdge[i]].c) {
                    mmin = edge[curEdge[i]].c;
                    pos = i;
                }
            }
;           for(i = s; i != e; i = edge[curEdge[i]].v) {
                edge[curEdge[i]].c -= mmin;
                edge[curEdge[i]^1].c += mmin;
            }
            maxflow += mmin;
            cur = pos;
        }
        for(i = curEdge[cur]; i != -1; i = edge[i].next)
            if(edge[i].c && h[cur] == h[edge[i].v] + 1)
                break;
        if(i != -1) {
            curEdge[cur] = i;
            pre[edge[i].v] = cur;
            cur = edge[i].v;
        } else {
            if(--numh[h[cur]] == 0) break;
            mmin = n;
            curEdge[cur] = fir[cur];
            for(i = fir[cur]; i != -1; i = edge[i].next) {
                if(edge[i].c && h[edge[i].v] < mmin)
                    mmin = h[edge[i].v];
            }
            h[cur] = mmin + 1;
            numh[h[cur]] ++;
            if(cur != s) cur = pre[cur];
        }
    }
    return maxflow;
}

int main() {

    char in[16];
    while(~scanf("%d%d%d%d", &n, &np, &nc, &m)) {
        int a, b, c;
        init();
        for(int i = 0; i < m; i++) {
            scanf("%s", in);
            a = b = c = 0;
            int bas = 1;
            int len = strlen(in);
            while(in[--len] != ')') {
                c += (in[len] - '0') * bas;
                bas *= 10;
            }
            bas = 1;
            while(in[--len] != ',') {
                b += (in[len] - '0') * bas;
                bas *= 10;
            }

            bas = 1;
            while(in[--len] != '(') {
                a += (in[len] - '0') * bas;
                bas *= 10;
            }
            addEdge(a, b, c);
            addEdge(b, a, 0);
        }
        for(int i = 0; i < np; i++) {
            scanf("%s", in);
            a = c = 0;
            int len = strlen(in);
            int bas = 1;
            while(in[--len] != ')') {

                c += (in[len] - '0') * bas;
                bas *= 10;
            }
            bas = 1;
            while(in[--len] != '(') {
                a += (in[len] - '0') * bas;
                bas *= 10;
            }
            addEdge(n, a, c);
            addEdge(a, n, 0);
        }
        for(int i = 0; i < nc; i++) {
            scanf("%s", in);
            a = c = 0;
            int len = strlen(in);
            int bas = 1;
            while(in[--len] != ')') {
                c += (in[len] - '0') * bas;
                bas *= 10;
            }
            bas = 1;
            while(in[--len] != '(') {
                a += (in[len] - '0') * bas;
                bas *= 10;
            }
            addEdge(a, n+1, c);
            addEdge(n+1, a, 0);
        }
        n += 2;
        printf("%d\n", SAP(n-2, n-1));
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值