Cod sursa(job #2962047)

Utilizator radubuzas08Buzas Radu radubuzas08 Data 7 ianuarie 2023 17:58:30
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.62 kb
#include <fstream>
#include <vector>
#include <queue>
using namespace std;

ifstream in("cuplaj.in");
ofstream out("cuplaj.out");
int l, r, m;
class Flow
{
    int source, sink;
    int n;
    int maxFlow;
    std::vector<bool> visited;
    std::vector<std::vector<int> > graph;
    std::vector<int> father;

    struct Edge {
        int from, to, flow;
    };

    vector<Edge> edges;
    int edgeCount;

    bool bfs()
    {
        visited.assign(n+1, false);
        std::queue<int> q;
        q.push(source);
        visited[source] = true;

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

            for(int edgeID : graph[node])
            {
                Edge const &e = edges[edgeID];
                int to = e.to;
                if(!e.flow || visited[to])
                    continue;
                visited[to] = true;
                q.push(to);
                father[to] = edgeID;
                if(to == sink)
                    return true;
            }
        }
        return false;
    }


public:
    Flow(int n, int source, int sink)
    {
        this->source = source;
        this->sink = sink;
        this->n = n;
        this->maxFlow = 0;
        this->edgeCount = -1;
        graph.resize(n + 1);
        visited.resize(n + 1);
        father.resize(n + 1);
    }

    void addEdge(int x, int y, int cost = 1)
    {
        graph[x].push_back(++edgeCount);
        edges.push_back({x, y, cost});

        graph[y].push_back(++edgeCount);
        edges.push_back({y, x, 0});
    }

    int getMaxFlow()
    {
        maxFlow = 0;
        do{
            if( !bfs() )
                break;
            for (auto edgeID : graph[sink]) {
                int to = edges[edgeID].to;
                if(!edges[edgeID ^ 1].flow || !visited[to])
                    continue;

                father[sink] = edgeID ^ 1;
                int flowMin = 0x7fffffff;
                for (int i = sink; i != source; i = edges[father[i]].from)
                    flowMin = std::min(flowMin, edges[father[i]].flow);
                if (flowMin == 0)
                    continue;

                maxFlow += flowMin;
                for (int i = sink; i != source; i = edges[father[i]].from) {
                    edges[father[i]].flow -= flowMin;
                    edges[father[i] ^ 1].flow += flowMin;
                }
            }
        } while (true);
        return maxFlow;
    }

    int getFlow() const{
        return maxFlow;
    }

//    std::vector<std::pair<int, int>> getMinCut()
//    {
//        visited.assign(n+1, false);
//        for (int i = 1; i <= n/2; ++i) {
//            flow[source][i] = 0;
//        }
//
//        dfs(source);
//        std::vector<std::pair<int, int>> minCut;
//        for (int i = source; i <= sink; ++i) {
//            for (int j : graph[i]) {
//                if (visited[i] && !visited[j] && capacity[i][j] > 0)
//                    minCut.emplace_back(i, j);
//            }
//        }
//        return minCut;
//    }

    void printGraph() {
        for (int i = 0; i <= edgeCount; ++i) {
            if(edges[i].from <= l && edges[i].to > l && !edges[i].flow)
                out << edges[i].from << ' ' << edges[i].to - l << '\n';
        }
    }
};

int main() {
    in >> l >> r >> m;
    Flow f(l + r + 1, 0, l + r + 1);

    for (int i = 1; i <= l; ++i)
        f.addEdge(0, i);
    for (int i = l + 1; i <= l + r; ++i)
        f.addEdge(i, l + r + 1);

    int x, y;
    while (m--) {
        in >> x >> y;
        f.addEdge(x, l + y);
    }
    in.close();

    int sol = f.getMaxFlow();

    out << sol << '\n';
    f.printGraph();
    out.close();
    return 0;
}