Cod sursa(job #2957767)

Utilizator BluThund3rRadu George BluThund3r Data 23 decembrie 2022 14:29:17
Problema Cuplaj maxim in graf bipartit Scor 20
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.25 kb
/*
    
*/

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

class Solution {
    int n, m, nrLeft;
    vector<vector<int>> capacity, flow, adj;
    vector<bool> viz;
    vector<int> parent;

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

bool Solution::bfs(int src) {
    fill(viz.begin(), viz.end(), false);
    fill(parent.begin(), parent.end(), -1);
    queue<int> q;
    q.push(src);
    viz[src] = true;

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

        for(auto nextNode : adj[currNode]) 
            if(!viz[nextNode] && capacity[currNode][nextNode] - flow[currNode][nextNode] > 0) {
                viz[nextNode] = true;
                if(nextNode != n) {
                    q.push(nextNode);
                    parent[nextNode] = currNode;
                }
            }
    }   

    return viz[n];  
} 

pair<int, vector<pair<int, int>>> Solution::findMatching(int s, int t) {
    int maxFlow = 0;
    vector<pair<int, int>> matchingEdges;
    while(bfs(s)) {
        for(auto leaf : adj[t]) {
            if(capacity[leaf][t] - flow[leaf][t] <= 0 || !viz[leaf])        
                continue;

            
            parent[t] = leaf;
            int minValOnPath = 110000;
            for(int node = t; parent[node] != -1; node = parent[node])
                minValOnPath = min(minValOnPath, capacity[parent[node]][node] - flow[parent[node]][node]);
            
            if(!minValOnPath)    
                continue;
            
            maxFlow += minValOnPath;

            for(int node = t; parent[node] != -1; node = parent[node]) {
                if(parent[node] != s && node != t)
                    matchingEdges.push_back({parent[node], node - nrLeft});
                flow[parent[node]][node] += minValOnPath;
                flow[node][parent[node]] -= minValOnPath;
            }
        }
    }

    return {maxFlow, matchingEdges};
}

Solution::Solution(int _n, int _m, vector<tuple<int, int, int>> edges, int nrLeft) {
    n = _n;
    m = _m;
    this->nrLeft = nrLeft;
    adj.resize(n + 1);
    viz.resize(n + 1);
    parent.resize(n + 1);
    capacity.resize(n + 1, vector<int>(n + 1, 0));
    flow.resize(n + 1, vector<int>(n + 1, 0));

    int x, y, c;
    for(auto& edge : edges) {
        x = get<0>(edge); y = get<1>(edge); c = get<2>(edge);
        capacity[x][y] = c;
        adj[x].push_back(y);
        adj[y].push_back(x);
    }
}

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

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

    Solution network(n + m + 1, e, edges, n);

    auto solution = network.findMatching(0, n + m + 1);
    out << solution.first << '\n';
    sort(solution.second.begin(), solution.second.end());
    for(auto edge : solution.second)
        out << edge.first << ' ' << edge.second << '\n';
    return 0;
}