Pagini recente » Cod sursa (job #906527) | Cod sursa (job #2182660) | Cod sursa (job #986377) | Cod sursa (job #1424959) | Cod sursa (job #1045774)
//
// 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>
#include <vector>
#include <queue>
#include <fstream>
using namespace std;
const int MAX_LEVEL = 12500001;
class Graph
{
private:
vector<vector<int> >* adj;
int sz;
public:
Graph(int vertices)
{
adj = new vector<vector<int> >(vertices + 1);
sz = 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);
}
vector<int>* adjacent_vertices(int v)
{
return &(adj -> at(v));
}
int size()
{
return sz;
}
};
class Matching
{
private:
Graph* graph;
vector<int>* matching;
vector<int>* dist;
int delimiter;
int size;
int matching_sz;
// is there an augmented path in the graph?
bool augmented_path()
{
queue<int> q;
for (int i = 1; i < delimiter; ++i)
{
if (matching -> at(i) == 0)
{
dist -> at(i) = 0;
q.push(i);
}
else
{
dist -> at(i) = MAX_LEVEL;
}
}
(*dist)[0] = MAX_LEVEL;
while (!q.empty())
{
int v = q.front();
q.pop();
if ((*dist)[v] < (*dist)[0])
{
vector<int>* adj = graph -> adjacent_vertices(v);
int adj_nodes = (int)adj -> size();
for (int i = 0; i < adj_nodes; ++i)
{
int u = adj -> at(i);
if (dist -> at(matching -> at(u)) == MAX_LEVEL)
{
dist -> at(matching -> at(u)) = dist -> at(v) + 1;
q.push(matching -> at(u));
}
}
}
}
return dist -> at(0) != MAX_LEVEL;
}
// augment
bool augment(int v)
{
if (v != 0)
{
vector<int>* adj = graph -> adjacent_vertices(v);
int adj_n = (int)adj -> size();
for (int i = 0; i < adj_n; ++i)
{
int u = adj -> at(i);
if (dist -> at(matching -> at(u)) == true)
{
(*matching)[u] = v;
(*matching)[v] = u;
return true;
}
}
(*dist)[v] = MAX_LEVEL;
return false;
}
else
{
return true;
}
}
int find_matching()
{
int matching_n = 0;
while (augmented_path())
{
for (int i = 1; i < delimiter; ++i)
{
if (matching -> at(i) == 0)
{
if (augment(i))
{
matching_n ++;
}
}
}
}
return matching_n;
}
public:
Matching(Graph* _graph, int _delimiter)
{
graph = _graph;
delimiter = _delimiter;
size = graph -> size();
matching = new vector<int>(size);
dist = new vector<int>(size);
for (int i = 0; i < size; ++i)
{
(*matching)[i] = 0;
}
matching_sz = find_matching();
}
int matching_size()
{
return matching_sz;
}
vector<int>* match()
{
return matching;
}
};
int main()
{
int N, M, P;
ifstream fin("cuplaj.in");
ofstream fout("cuplaj.out");
fin >> N >> M >> P;
cout << N << M << P;
Graph* graph = new Graph(N + M + 1);
for (int i = 0; i < P; ++i)
{
int x;
int y;
fin >> x;
fin >> y;
graph -> add_edge(x, y);
}
Matching* matching = new Matching(graph, N + 1);
fout << matching -> matching_size() << "\n";
vector<int>* match = matching -> match();
for (int i = 1; i < N; ++i)
{
if (match -> at(i) == match -> at (match -> at(i)))
{
fout << i << " " << match -> at(i) << "\n";
}
}
return 0;
}