Cod sursa(job #2888280)

Utilizator buzu.tudor67Tudor Buzu buzu.tudor67 Data 10 aprilie 2022 21:36:58
Problema Cuplaj maxim in graf bipartit Scor 50
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.41 kb
#include <bits/stdc++.h>
using namespace std;

class Graph{
public:
    const int N;
    vector<vector<int>> neighbors;
    vector<unordered_map<int, int>> capacity;

public:
    Graph(const int& N): N(N){
        neighbors.resize(N);
        capacity.resize(N);
    }

    void addEdge(int x, int y, int c){
        neighbors[x].push_back(y);
        neighbors[y].push_back(x);
        capacity[x][y] = c;
    }
};

class Dinic{
private:
    Graph& G;
    const int N;
    const int SRC;
    const int DEST;
    const int INF = 1e8;
    vector<vector<int>> f;
    vector<int> dist;
    vector<int> startEdgeIdx;

    int bfs(){
        fill(dist.begin(), dist.end(), INF);
        
        queue<int> q;
        q.push(SRC);
        dist[SRC] = 0;
        while(!q.empty() && dist[DEST] == INF){
            int node = q.front();
            q.pop();

            for(int nextNode: G.neighbors[node]){
                int remainingCapacity = G.capacity[node][nextNode] - f[node][nextNode];
                if(remainingCapacity > 0 && dist[nextNode] == INF){
                    dist[nextNode] = 1 + dist[node];
                    q.push(nextNode);
                }
            }
        }

        return (dist[DEST] != INF);
    }

    int dfs(int node, int minDelta){
        if(node == DEST){
            return minDelta;
        }
        for(; startEdgeIdx[node] < (int)G.neighbors[node].size(); ++startEdgeIdx[node]){
            int nextNode = G.neighbors[node][startEdgeIdx[node]];
            int remainingCapacity = G.capacity[node][nextNode] - f[node][nextNode];
            if(remainingCapacity > 0 && dist[node] + 1 == dist[nextNode]){
                int delta = dfs(nextNode, min(minDelta, remainingCapacity));
                if(delta > 0){
                    f[node][nextNode] += delta;
                    f[nextNode][node] -= delta;
                    return delta;
                }
            }
        }
        return 0;
    }

public:
    Dinic(Graph& G, const int& SRC, const int& DEST):
          G(G), N(G.N), SRC(SRC), DEST(DEST){
    }

    int computeMaxFlow(){
        f.assign(N, vector<int>(N, 0));
        dist.resize(N);
        startEdgeIdx.resize(N);

        int maxFlow = 0;
        while(bfs()){
            fill(startEdgeIdx.begin(), startEdgeIdx.end(), 0);
            int delta = INF;
            while(delta > 0){
                delta = dfs(SRC, INF);
                maxFlow += delta;
            }
        }

        return maxFlow;
    }

    bool isSaturatedEdge(int x, int y) const{
        return (G.capacity[x][y] == f[x][y]);
    }
};

int main(){
    ifstream cin("cuplaj.in");
    ofstream cout("cuplaj.out");

    int N, M, E;
    cin >> N >> M >> E;

    const int TOTAL_NODES = N + M + 5;
    const int SRC = TOTAL_NODES - 2;
    const int DEST = TOTAL_NODES - 1;

    Graph G(TOTAL_NODES);
    int x, y;
    for(int i = 1; i <= E; ++i){
        cin >> x >> y;
        G.addEdge(x, N + y, 1);
    }

    for(int x = 1; x <= N; ++x){
        G.addEdge(SRC, x, 1);
    }

    for(int y = N + 1; y <= N + M; ++y){
        G.addEdge(y, DEST, 1);
    }

    Dinic dinic(G, SRC, DEST);
    
    int maxMatching = dinic.computeMaxFlow();
    cout << maxMatching << "\n";
    for(int x = 1; x <= N; ++x){
        for(int y: G.neighbors[x]){
            if(y != SRC && dinic.isSaturatedEdge(x, y)){
                cout << x << " " << (y - N) << "\n";
            }
        }
    }

    cin.close();
    cout.close();
    return 0;
}