Cod sursa(job #2500010)

Utilizator isa_tudor_andreiAndrei Tudor isa_tudor_andrei Data 27 noiembrie 2019 09:37:42
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.69 kb
#include <bits/stdc++.h>

using namespace std;

ifstream fin("cuplaj.in");
ofstream fout("cuplaj.out");

const int INF = 1000000;

struct Edge{
  int dest;
  int flow;
  int capacity;
  int rev;
};

class Residual_graph{
  public:
    int V;
    vector<Edge> *G;
    int *level;
  public:
    Residual_graph( int n ) {
      this->V = n;
      G = new vector<Edge>[V + 1];
      level = new int[V + 1];
    }

    void add_edge( int u, int v, int cap ) {
      Edge a{v, 0, cap, G[v].size()};
      Edge b{u, 0, 0, G[u].size()};

      G[u].push_back(a);
      G[v].push_back(b);
    }

    bool BFS( int source, int sink );
    int push_flow( int node, int sink, int flow, int start[] );
    int Dinic( int source, int sink );
};

bool Residual_graph::BFS( int source, int sink ) {

  for( int i = 1; i <= V; i ++ )
    level[i] = -1;

  level[source] = 0;
  queue<int> q;
  q.push(source);
  while( !q.empty() ) {
    int node = q.front();
    q.pop();
    for( auto it : G[node] )
      if( level[it.dest] == -1 && it.flow < it.capacity ) {
        level[it.dest] = level[node] + 1;
        q.push(it.dest);
      }
  }

  return (level[sink] > 0);
}

int Residual_graph::push_flow( int node, int sink, int flow, int start[] ) {

  if( node == sink )
    return flow;

  for( ; start[node] < G[node].size(); start[node] ++ ) {
    Edge &e = G[node][start[node]];

    if( level[e.dest] == level[node] + 1 && e.flow < e.capacity ) {
      int tempflow = push_flow(e.dest, sink, min(e.capacity - e.flow, flow), start);
      if( tempflow > 0 ) {
        e.flow += tempflow;
        G[e.dest][e.rev].flow -= tempflow;
        return tempflow;
      }
    }
  }
  return 0;
}

int Residual_graph::Dinic( int source, int sink ) {

  int totalflow = 0;
  while( BFS(source, sink) == true ) {
    int start[V + 1] = {0};
    while( int maxflow = push_flow(source,sink,INF,start) )
      totalflow += maxflow;
  }
  return totalflow;
}

int main() {
    int n, m, e;
    fin>>n>>m>>e;

    Residual_graph graph(n + m + 2);
    for( int i = 1; i <= e; i ++ ) {
      int a, b, c;
      fin>>a>>b;
      b += n;
      graph.add_edge(a, b, 1);
    }
    int super_source = n + m + 1;
    int super_sink = n + m + 2;
    for( int i = 1; i <= n; i ++ )
      graph.add_edge(super_source, i, 1);
    for( int i = n + 1; i <= n + m; i ++ )
      graph.add_edge(i, super_sink, 1);
    fout<<graph.Dinic(super_source,super_sink)<<"\n";
    for( int i = 1; i <= n + m; i ++ ) {
      for( auto it : graph.G[i] )
        if( it.flow == 1 && it.dest != super_sink && it.dest != super_source )
          fout<<i<<" "<<it.dest - n<<"\n";
    }
    return 0;
}