최대 흐름, 최소 비용 최대 흐름 【 템 플 릿 】

코드 저작권: HIT   xiaodai
최대 스 트림 템 플 릿: (제목 링크)
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
#define N 1200
#define M 50220
#define INF 0x3f3f3f3f

class MaxFlow {
public:
    struct record {
        int v, f, next;
    } edge[M];
    int n, s, t;
    int pos[N], dis[N], vh[N], cl;
    int his[N], di[N], pre[N];

    void AddEdge(int a, int b, int f) {
        cl++;
        edge[cl].next = pos[a];
        edge[cl].v = b;
        edge[cl].f = f;
        pos[a] = cl;
        cl++;
        edge[cl].next = pos[b];
        edge[cl].v = a;
        edge[cl].f = 0; //     , f = f
        pos[b] = cl;
    }
    void Init() {
        cl = 1;
        memset(dis, 0, sizeof(dis));
        memset(vh, 0, sizeof(vh));
        memset(pos, 0, sizeof(pos));
    }
    int flow() {
        vh[0] = n; //   GAP  (            0,      0     n)
        for (int i = 0; i < n; i++) di[i] = pos[i]; //      
        int i = s, aug = INF, flow = 0; //       ,flow     ,aug         
        bool flag = false; //    ,            (            )
        while (dis[s] < n) {
            his[i] = aug; //      
            flag = false;
            for (int p=di[i]; p; p=edge[p].next)
                if ((edge[p].f > 0) && (dis[edge[p].v] + 1 == dis[i])) {//           
                    flag = true; //     
                    di[i] = p; //     
                    aug = min(aug, edge[p].f); //      
                    pre[edge[p].v] = p; //      
                    i = edge[p].v; //       
                    if (i == t) {//    ,      
                        flow += aug; //      
                        while (i != s) {//            ,         
                            edge[pre[i]].f -= aug;
                            edge[pre[i]^1].f += aug;
                            i = edge[pre[i]^1].v;
                        }
                        aug = INF;
                    }
                    break;
                }
            if (flag) continue; //         ,      
            int min = n - 1;
            for (int p=pos[i]; p; p=edge[p].next)
                if ((edge[p].f > 0) && (dis[edge[p].v] < min)) {
                    di[i] = p; //         
                    min = dis[edge[p].v];
                }

            --vh[dis[i]];
            if (vh[dis[i]] == 0) break; //  vh  ,       ,     (GAP  )
            dis[i] = min + 1;
            ++vh[dis[i]];
            if (i != s) {//    
                i = edge[pre[i]^1].v;
                aug = his[i];
            }
        }
        return flow;
    }
} net;

int n, b, g[1002][22], s[22];

void init(int x, int y) {
    net.Init();

    net.s = 0, net.t = n+b+1, net.n = n+b+2;
    for (int i=1; i<=n; i++) net.AddEdge(0, i, 1);
    for (int i=1; i<=n; i++) for (int j=x; j<=y; j++)
            net.AddEdge(i, g[i][j]+n, 1);
    for (int i=1; i<=b; i++) net.AddEdge(n+i, net.t, s[i]);
}
int main() {
    scanf("%d%d", &n, &b);
    for (int i=1; i<=n; i++) for (int j=1; j<=b; j++) scanf(" %d", &g[i][j]);
    for (int i=1; i<=b; i++) scanf("%d", &s[i]);
    int ans = INF;

    for (int i=1; i<=b; i++) for (int j=i; j<=b; j++) {
            init(i, j);
            if (net.flow() == n) ans = min(ans, j-i+1);
        }
    printf("%d
", ans); return 0; }
/*
 *         
 *       (SPFA)
 * O(Maxflow(G)*kV)
 * HIT_ACM 2012 Summer Camp
 * by xiaodai
 */
#include <iostream>
#include <queue>
#include <cstring>
#include <cstdio>

#define SETZR(a) memset(a,0,sizeof(a))

using namespace std;

const int maxn = 10000;
const int maxm = 1000000;
const int INF = 1000000000;

struct record {
    int v, f, c, next;
} edge[maxm];

int cas, ans, cl, n, m, s, t, aug, k, p;
int dist[maxn], pre[maxn], pointer[maxn];
bool vis[maxn];
queue<int> q;

void connect(int a, int b, int f, int c) {
    cl++;
    edge[cl].next = pointer[a];
    edge[cl].v = b;
    edge[cl].f = f;
    edge[cl].c = c;
    pointer[a] = cl;
    cl++;
    edge[cl].next = pointer[b];
    edge[cl].v = a;
    edge[cl].f = 0;
    edge[cl].c = -c;
    pointer[b] = cl;
}

bool spfa() {
    memset(vis, 0, sizeof (vis));
    for (int i = 0; i < n; i++) dist[i] = INF;
    q.push(s);
    dist[s] = 0;
    pre[s] = 0;
    while (!q.empty()) {
        k = q.front();
        q.pop();
        vis[k] = 0;
        for (p=pointer[k]; p; p=edge[p].next)
            if ((edge[p].f > 0) && (edge[p].c + dist[k] < dist[edge[p].v])) {
                dist[edge[p].v] = edge[p].c + dist[k];
                pre[edge[p].v] = p;
                if (!vis[edge[p].v]) {
                    q.push(edge[p].v);
                    vis[edge[p].v] = 1;
                }
            }
    }
    if (dist[t] == INF) return false;
    aug = INF;
    for (p=re[t]; p; p=pre[edge[p^1].v])
        aug = min(aug, edge[p].f);
    
    for (p=pre[t]; p; p=pre[edge[p^1].v]) {
        edge[p].f -= aug;
        edge[p^1].f += aug;
    }
    ans += dist[t] * aug;
    return true;
}

int main() {
    scanf("%d", &cas);
    while (cas--) {
        cl = 1;
        scanf("%d%d%d%d", &n, &m, &s, &t);
        SETZR(pointer);
        for (int i = 0; i < m; i++) {
            int p, k, f, c;
            scanf("%d%d%d%d", &p, &k, &f, &c);
            connect(p, k, f, c);
        }
        ans = 0;
        while (spfa())  ;
        printf("%d
", ans); } return 0; }

좋은 웹페이지 즐겨찾기