Cod sursa(job #1666991)

Utilizator bciobanuBogdan Ciobanu bciobanu Data 28 martie 2016 15:55:13
Problema Cc Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.21 kb
#include <bits/stdc++.h>

using namespace std;

#define NIL -1

struct Edge {
    int v;
    int cost, cap;
    int next;
};

Edge G[2 * (100 * 100 + 200)];
int head[205];

int D[205];
bool inQueue[205];
int Q[256];

int pointer[205];
int dad[205];

bool bellmanFord(int n) {
    int st, fn;
    memset(D + 1, 0x3f, 4 * 204);
    Q[0] = 0;
    st = 0; fn = 1;
    while(st != fn) {
        int u = Q[(st ++) & 255];
        inQueue[u] = 0;
        for(int i = head[u]; i != NIL; i = G[i].next) {
            int v = G[i].v;
            if(G[i].cap && G[i].cost + D[u] < D[v]) {
                D[v] = G[i].cost + D[u];
                pointer[v] = i;
                dad[v] = u;
                if(!inQueue[v]) {
                    inQueue[v] = 1;
                    Q[(fn ++) & 255] = v;
                }
            }
        }
    }
    return D[2 * n + 1] != 0x3f3f3f3f;
}

void addEdge(int u, int v, int cap, int cost) {
    static int pos = 0;
    G[pos].v = v;
    G[pos].cap = cap;
    G[pos].cost = cost;
    G[pos].next = head[u];
    head[u] = pos++;
}

int main() {
    freopen("cc.in", "r", stdin);
    freopen("cc.out", "w", stdout);

    int n;

    cin >> n;

    for(int i = 0; i <= 2 * n + 1; ++ i) {
        head[i] = NIL;
    }

    for(int i = 1; i <= n; ++ i) {
        for(int j = 1; j <= n; ++ j) {
            int cost;
            cin >> cost;
            addEdge(i, j + n, 1, cost);
            addEdge(j + n, i, 0, -cost);
        }
    }

    // SS
    for(int i = 1; i <= n; ++ i) {
        addEdge(0, i, 1, 0);
        addEdge(i, 0, 0, 0);
    }

    // SD
    for(int i = 1; i <= n; ++ i) {
        addEdge(2 * n + 1, i + n, 0, 0);
        addEdge(i + n, 2 * n + 1, 1, 0);
    }

    int ret = 0;
    int minFlow;
    while(bellmanFord(n)) {
        ret += D[2 * n + 1];
        minFlow = 0x3f3f3f3f;
        for(int i = 2 * n + 1; i != 0; i = dad[i]) {
            minFlow = min(minFlow, G[pointer[i]].cap);
        }
        for(int i = 2 * n + 1; i != 0; i = dad[i]) {
            G[pointer[i]].cap -= minFlow;
            G[pointer[i] ^ 1].cap += minFlow;
        }
    }

    cout << ret << '\n';

    return 0;
}