Pagini recente » Cod sursa (job #2649896) | Cod sursa (job #1565085) | Cod sursa (job #1554735) | Cod sursa (job #2563071) | Cod sursa (job #2968688)
#include <stdio.h>
// represents no node, no edge, no value etc.
#define NONE (-1)
// represents infinity
#define INF (0x3f3f3f3f)
// the maximum dimensions of the graph
#define NMAX (10'000)
#define MMAX (10'000)
#define EMAX (100'000)
// the graph
struct
{
// the edges of the graph
struct
{
int v; // the node this edge leads to
bool maximal; // whether or not the edge is in the maximal cardinality matching
int next; // the next edge
} edges[2 * EMAX];
// the first edge of each node
int begin[NMAX + MMAX];
// the depths of the nodes
int depth[NMAX + MMAX];
// for each node, whether or not it is free
int free[NMAX + MMAX];
// the no. of nodes and no. of edges
int n, m, e;
// init the graph with _n nodes
void init(int _n, int _m)
{
n = _n; m = _m;
for(int u = 0; u < n + m; u++)
{
begin[u] = NONE;
free[u] = true;
}
}
// adds an edge from u to v that is in the maximal cardinality matching if maximal
void add_edge(int u, int v, bool maximal)
{
edges[e] = { v, maximal, begin[u] };
begin[u] = e++;
}
// BFS queue
int queue[NMAX + MMAX];
int qtop;
// BFS on unmatched edges to calculate the depths; returns true if at least one augmenting path was found
bool bfs()
{
// init the queue
qtop = 0;
for(int u = 0; u < n; u++)
if(free[u])
{
// if u is free, add it as starting vertex
depth[u] = 0;
queue[qtop++] = u;
}
else // else, set its depth to infinity
depth[u] = INF;
// set the depths to all nodes in V to infinity
for(int u = 0; u < m; u++)
depth[u + n] = INF;
// the depth of the shortest augmenting path
int aug = INF;
// while the queue isn't empty
for(int qfront = 0; qfront < qtop; qfront++)
{
// the current vertex
int u = queue[qfront];
// ignore if it is at the depth of the shortest augmenting path
if(depth[u] == aug)
continue;
// go through the neighbours
for(int i = begin[u]; i != NONE; i = edges[i].next)
{
int v = edges[i].v; // the next node
bool maximal = edges[i].maximal; // whether or not the edge is maximal
// if the edge is not maximal, go through it
if(!maximal && depth[v] == INF)
{
depth[v] = depth[u] + 1;
queue[qtop++] = v;
// if we've found a free vertex, set the depth of the augmenting path
if(free[v])
aug = depth[v];
}
}
}
// we've found augmenting paths if aug != INF
return aug != INF;
}
// DFS from u to find the augmenting paths and add them to the maximal matching
bool dfs(int u)
{
// base case; u is free so set it to not free and return
if(free[u])
{
free[u] = false;
depth[u] = INF;
return true;
}
// go through the neighbours and check DFS
for(int i = begin[u]; i != NONE; i = edges[i].next)
{
int v = edges[i].v;
// if the depth is increasing by 1
if(depth[v] == depth[u] + 1)
{
// recursive call
if(dfs(v))
{
// add the edge to matching, set u's depth to infinity and return
edges[i].maximal = !edges[i].maximal;
edges[i ^ 1].maximal = !edges[i ^ 1].maximal;
depth[u] = INF;
return true;
}
}
}
// set u's depth to infinity and return
depth[u] = INF;
return false;
}
// Hopcroft-Karp to find the maximal cardinality matching
int hopcroft_karp()
{
// the size of the matching
int matching = 0;
// where there are augmenting paths
while(bfs())
{
// go through the free nodes in U
for(int u = 0; u < n; u++)
if(free[u])
{
// mark it as not free and try to find path
free[u] = false;
if(dfs(u))
{
// if a path was found, count it
matching = matching + 1;
}
else // else, set u back to free
free[u] = true;
}
}
// return the answer
return matching;
}
} graph;
int main()
{
// open the files
freopen("cuplaj.in", "r", stdin);
freopen("cuplaj.out", "w", stdout);
// read the graph
int n, m, e;
scanf("%d %d %d", &n, &m, &e);
// init the graph
graph.init(n, m);
// read the edges
for(int i = 0; i < e; i++)
{
int u, v;
scanf("%d %d", &u, &v);
u--; v--;
graph.add_edge(u, v + n, false);
graph.add_edge(v + n, u, true);
}
// print the maximal cardinality matching size
printf("%d\n", graph.hopcroft_karp());
// print the edges in the matching
for(int u = 0; u < n; u++)
for(int i = graph.begin[u]; i != NONE; i = graph.edges[i].next)
if(graph.edges[i].maximal)
printf("%d %d\n", u + 1, graph.edges[i].v - n + 1);
// exit
return 0;
}