Cod sursa(job #1551000)

Utilizator andrei.arnautuAndi Arnautu andrei.arnautu Data 15 decembrie 2015 00:30:36
Problema Cuplaj maxim in graf bipartit Scor 50
Compilator cpp Status done
Runda Arhiva educationala Marime 2.85 kb
/**
  *  Worg
  *  Cuplaj -> Dinic's Algorithm
  */
#include <queue>
#include <cstdio>
#include <vector>

using namespace std;
FILE *fin = freopen("cuplaj.in", "r", stdin);
FILE *fout = freopen("cuplaj.out", "w", stdout);

const int MAX_N = 10000, DIM = 2 * (1 + MAX_N), MAX_INF = 0x3fffffff;

vector < int > G[DIM];    /* general */
vector < pair<int,int> > edges;
int cap[DIM][DIM];
int n, m, e;

queue < int > q; /* flow */
vector < int > GL[DIM];
int depth[DIM], path[DIM];
int S, D;
bool checked[DIM];

void readData() {

    scanf("%d%d%d", &n, &m, &e);
    S = 0; D = n + m + 1;
    for(int i = 1; i <= n; ++i) {

        G[S].push_back(i); G[i].push_back(S);
        cap[S][i] = 1;
    }
    for(int i = n + 1; i <= n + m; ++i) {

        G[i].push_back(D); G[D].push_back(i);
        cap[i][D] = 1;
    }
    for(int i = 1; i <= e; ++i) {

        int x, y; scanf("%d%d", &x, &y);
        y += n;
        G[x].push_back(y); G[y].push_back(x); edges.push_back(make_pair(x, y));
        cap[x][y] = 1;
    }
}

bool buildGL() {

    for(int i = S; i <= D; ++i) {
        checked[i] = false;
    }
    int node = S;
    q.push(node); checked[node] = true; depth[node] = 0;
    while(!q.empty()) {

        node = q.front(); q.pop();
        for(int nxt : G[node])
            if(!checked[nxt] && cap[node][nxt] > 0) {

                checked[nxt] = true;
                depth[nxt] = depth[node] + 1;
                q.push(nxt);
            }
    }
    for(int i = S; i <= D; ++i)
        GL[i].clear();
    for(int i = S; i <= D; ++i)
        for(int nxt : G[i])
            if(depth[i] - depth[nxt] == -1 && cap[i][nxt] > 0)
                GL[i].push_back(nxt);
    return checked[D];
}

int DFS(int node) {

    checked[node] = true; path[depth[node]] = node;
    if(node == D) {

        return MAX_INF;
    }
    else {

        for(int nxt : GL[node])
            if(!checked[nxt] && cap[node][nxt]) {

                int x = DFS(nxt);
                if(x > 0)
                    return min(cap[node][nxt], x);
            }
        return 0;
    }
}

int pushFlow() {

    for(int i = S; i <= D; ++i)
        checked[i] = false;
    int currentFlow = 0, flow = DFS(S);
    while(flow) {

        for(int i = 0; i < depth[D]; ++i) {

            cap[path[i]][path[i + 1]] -= flow;
            cap[path[i + 1]][path[i]] += flow;
        }
        currentFlow += flow;
        for(int i = S; i <= D; ++i)
            checked[i] = false;
        flow = DFS(S);
    }
    return currentFlow;
}

int main() {

    readData();
    int totalFlow = 0;
    while(buildGL())
        totalFlow += pushFlow();
    printf("%d\n", totalFlow);
    for(pair <int,int> p : edges)
        if(!cap[p.first][p.second])
            printf("%d %d\n", p.first, p.second - n);
    return 0;
}