poj1459SAP最大流模板题

最大流建图是关键,将一个题目转化为最大流,要有清晰的建图思想。

这道题注意构建源点和汇点,然后直接套模板。

 

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;

const int maxn = 220;
const int inf = 10000000;//不要开太大
int c[maxn][maxn];
int q[maxn], pre[maxn];
int level[maxn], gap[maxn];
int n, m, np, nc;
int s, t;
void init_sap(){
    memset(level,  10, sizeof (level));
    //printf("---    %d\n", level[2]);
    //for(int i = 0; i <= n; i ++) level[i] =  n + 310;
    memset(gap, 0, sizeof gap);
    memset(pre, -1, sizeof pre);
    int qs = 0, qe = 0;
    q[qe++] = t;
    level[t] = 0;
    gap[ level[t] ] ++;
    while(qs < qe){
        int hd = q[qs++];
        for(int i = 1; i <= n; i ++){
            if(level[i] > n && c[i][hd] > 0){//level[i] >= n  也可以,why ?
                q[qe++] = i;
                level[i] = level[hd] + 1;
                gap[ level[i] ] ++;
            }
        }
    }
}
int find_path(int u){
    for(int i = 1; i <= n; i ++)
      if(c[u][i] > 0 && level[u] == level[i] + 1) return i;
    return -1;
}
int relabel(int u){
    int tmp = inf;
    for(int i = 1; i <= n; i ++)
      if(c[u][i] > 0 && tmp > level[i] + 1)
        tmp = level[i] + 1;
    if(tmp == inf) tmp = n;
    return tmp;
}
int sap(){
    init_sap();
    int flow = 0, u = s;
    while(level[s] <= n){
        int v = find_path(u);
        if(v > 0){
            pre[v] = u;
            u = v;
            if(u == t){
                int min_flow = inf;
                for(int i = t; i != s; i = pre[i])
                  if(min_flow > c[ pre[i]][i])
                    min_flow = c[ pre[i]][i];
                for(int i = t; i != s; i = pre[i]){
                    c[pre[i]][i] -= min_flow;
                    c[i][pre[i]] += min_flow;
                }
                flow += min_flow;
                u = s;
            }
        }else{
            if(-- gap[ level[u]] == 0) return flow;
            int v = relabel(u);
            gap[v] ++;
            level[u] = v;
            if(u != s) u = pre[u];
        }
    }
    return flow;
}
int main(){
    while(~scanf("%d%d%d%d", &n, &np, &nc,& m)){
        memset(c, 0, sizeof c);
        s=n+1,t=n+1+1,n+=2;
        //cout<<s<<endl;
        for(int i = 1; i <= m; i ++){
            int u, v, w;
            scanf(" (%d,%d)%d", &u, &v, &w);
            c[u+1][v+1] += w;
        }
        for(int i = 1; i <= np; i ++)
        {
            int v, w;
            scanf(" (%d)%d", &v, &w);
            c[s][v+1] = w;
        }
        for(int i = 1; i <=nc; i ++){
            int u, w;
            scanf(" (%d)%d", &u, &w);
            c[u+1][t] = w;
        }
        /*for(int i=1;i<=n;i++)
        {
            cout<<endl;
            for(int j=1;j<=n;j++)
            cout<<c[i][j]<<' ';
        }*/

        int flow = sap();
        printf("%d\n", flow);
    }
    return 0;
}


 

posted @ 2013-04-30 20:38  amourjun  阅读(178)  评论(0编辑  收藏  举报