Cod sursa(job #2958080)

Utilizator BluThund3rRadu George BluThund3r Data 24 decembrie 2022 15:10:07
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.58 kb
/*
    
*/

#include <bits/stdc++.h>
using namespace std;
ifstream in("cuplaj.in");
ofstream out("cuplaj.out");

class Solution {
    int n, nrLeft;
    struct edge {
        int src, dst, capacity, flow;
        edge* back;
    };
    vector<vector<edge*>> adj;
    vector<edge*> parent;

    void appendEdges(int x, int y) {
        edge* e1 = new edge;
        edge* e2 = new edge;

        e1->back = e2;
        e2->back = e1;
    
        e1->src = x;
        e1->dst = y;
        e1->capacity = 1;
        e2->flow = e1->flow = 0;
        e2->src = y;
        e2->dst = x;
        e2->capacity = 0;

        adj[x].push_back(e1);
        adj[y].push_back(e2);
    }

public:
    Solution(int _n, int nrLeft, vector<pair<int, int>> edges);
    bool bfs(int src, int dist);
   void findMatching(int s, int t);
};

bool Solution::bfs(int src, int dest) {
    fill(parent.begin(), parent.end(), nullptr);
    queue<int> q;
    q.push(src);

    int currNode;
    while(!q.empty()) {
        currNode = q.front();
        q.pop();        

        for(auto nextEdge : adj[currNode])  {
            int nextNode = nextEdge->dst;
            if(!parent[nextNode] && nextEdge->capacity - nextEdge->flow > 0) {
                parent[nextNode] = nextEdge;
                if(nextNode != dest) {
                    q.push(nextNode);
                }
            }
        }
    }   

    return parent[dest] != nullptr;  
} 

void Solution::findMatching(int s, int t) {
    int maxFlow = 0;
    while(bfs(s, t)) {
        for(auto terminalEdge : adj[t]) {
            if(terminalEdge->back->capacity - terminalEdge->back->flow <= 0 || !parent[terminalEdge->dst])        
                continue;
            
            parent[t] = terminalEdge->back;
            int minValOnPath = 1e6;
            for(auto current = t; current != s; current = parent[current]->src)
                minValOnPath = min(minValOnPath, parent[current]->capacity - parent[current]->flow);
            
            if(!minValOnPath)    
                continue;
            
            maxFlow += minValOnPath;

            // for(int node = t; parent[node] != -1; node = parent[node]){
            //     flow[parent[node]][node] += minValOnPath;
            //     flow[node][parent[node]] -= minValOnPath;
            // }
            
            for(auto current = t; current != s; current = parent[current]->src) {
                parent[current]->flow += minValOnPath;
                parent[current]->back->flow -= minValOnPath;
            }
        }
    }

    out << maxFlow << '\n';
    for(int i = 1; i <= nrLeft; ++ i) {
        for(auto edge : adj[i]){
            if(edge->dst == s) 
                continue;
            if(edge->capacity - edge->flow == 0)
                out << i << ' ' << edge->dst - nrLeft << '\n';
        }
    }
}

Solution::Solution(int _n, int nrLeft, vector<pair<int, int>> edges): n(_n), nrLeft(nrLeft) {
    adj.resize(n + 1);
    parent.resize(n + 1);

    int x, y;
    for(auto& edge : edges) {
        x = edge.first; y = edge.second;
        appendEdges(x, y);
    }
}

int main() {
    vector<pair<int, int>> edges;
    int n, m, x, y, e;

    in >> n >> m >> e;
    while(e --) {
        in >> x >> y;
        edges.push_back({x, n + y});
    }

    for(int i = 1; i <= n; ++ i) 
        edges.push_back({0, i});
    
    for(int i = 1; i <= m; ++ i)
        edges.push_back({n + i, n + m + 1});

    Solution network(n + m + 1, n, edges);
    network.findMatching(0, n + m + 1);
    return 0;
}