Pagini recente » Cod sursa (job #2509726) | Cod sursa (job #2823298) | Cod sursa (job #1250581) | Cod sursa (job #928470) | Cod sursa (job #1046518)
//
// Infoarena - Cuplaj Maxim In Graf Bipartit
//
// http://www.infoarena.ro/problema/cuplaj
//
// Robert M. Badea
//
// I really need to set up a convention
// for these comments tho.
//
#include <iostream> // <-- You don't need this, remove it.
#include <fstream>
#include <vector>
#include <queue>
using namespace std;
class Graph
{
private:
vector<vector<int> >* adj;
int vertices_n;
public:
Graph(int vertices)
{
adj = new vector<vector<int> >(vertices + 1);
vertices_n = vertices;
}
void add_edge(int a, int b)
{
if (a == 0 || b == 0)
{
throw 201;
}
adj -> at(a).push_back(b);
adj -> at(b).push_back(a);
}
void add_directed_edge(int a, int b)
{
if (a == 0 || b == 0)
{
throw 201;
}
adj -> at(a).push_back(b);
}
vector<int>* adjacent_vertices(int v)
{
return &(adj -> at(v));
}
int size()
{
return vertices_n;
}
};
class Matching
{
private:
Graph* graph;
vector<int>* left_to_right;
vector<int>* right_to_left;
vector<bool>* used;
int matching_size;
bool pairup(int vertex)
{
// cout << "V: " << vertex << "\n";
if (used -> at(vertex))
{
return false;
}
(*used)[vertex] = true;
vector<int>* adjacent_vertices = graph -> adjacent_vertices(vertex);
int adjacent_vertices_n = (int)adjacent_vertices -> size();
for (int i = 0; i < adjacent_vertices_n; ++i)
{
int v = vertex;
int u = adjacent_vertices -> at(i);
if (right_to_left -> at(u) == 0)
{
(*left_to_right)[v] = u;
(*right_to_left)[u] = v;
// cout << "Linking " << v << " and " << u << ".\n";
return true;
}
}
for (int i = 0; i < adjacent_vertices_n; ++i)
{
int v = vertex;
int u = adjacent_vertices -> at(i);
// cout << v << " - " << u << "\n";
if (pairup(right_to_left -> at(u)))
{
(*left_to_right)[v] = u;
(*right_to_left)[u] = v;
// cout << "Linking " << v << " and " << u << ".\n";
return true;
}
}
return false;
}
void make_matching()
{
int there_is_something_to_do = true;
while (there_is_something_to_do)
{
there_is_something_to_do = false;
for (int i = 1; i <= used -> size(); ++i)
{
(*used)[i] = false;
}
for (int i = 1; i <= graph -> size(); ++i)
{
if (left_to_right -> at(i) == 0)
{
there_is_something_to_do = pairup(i) || there_is_something_to_do;
}
// cout << there_is_something_to_do << "\n";
}
// cout << "Done, next one.\n";
}
}
void make_matching_size()
{
int size = 0;
for (int i = 0; i < left_to_right -> size(); ++i)
{
size += left_to_right -> at(i) != 0;
}
matching_size = size;
}
public:
Matching(Graph* _graph, int left_vertices_n, int right_vertices_n)
{
graph = _graph;
used = new vector<bool>(graph -> size() + 1);
left_to_right = new vector<int>(left_vertices_n + 1);
right_to_left = new vector<int>(right_vertices_n + 1);
make_matching();
make_matching_size();
}
vector<int>* left()
{
return left_to_right;
}
vector<int>* right()
{
return right_to_left;
}
int size()
{
return matching_size;
}
};
int main()
{
ifstream fin ("cuplaj.in");
ofstream fout ("cuplaj.out");
int N, M, E;
// cout << "Start!\n";
fin >> N >> M >> E;
Graph* graph = new Graph(N);
for (int i = 0; i < E; ++i)
{
int a, b;
fin >> a >> b;
graph -> add_directed_edge(a, b);
}
// cout << "Getting in...\n";
Matching* matching = new Matching(graph, N, M);
// cout << "Got out.\n";
vector<int>* left = matching -> left();
int size = matching -> size();
fout << size << "\n";
for (int i = 0; i < left -> size(); ++i)
{
if (left -> at(i) != 0)
{
fout << i << " " << left -> at(i) << "\n";
}
}
fin. close();
fout.close();
return 0;
}