Pagini recente » Cod sursa (job #338524) | Cod sursa (job #1671008) | Cod sursa (job #3290229) | Cod sursa (job #1685228) | Cod sursa (job #2874702)
#include <bits/stdc++.h>
using namespace std;
class InParser
{
private:
FILE *fin;
char *buff;
int sp;
char read_ch()
{
++sp;
if (sp == 4096)
{
sp = 0;
fread(buff, 1, 4096, fin);
}
return buff[sp];
}
public:
InParser(const char *nume)
{
fin = fopen(nume, "r");
buff = new char[4096]();
sp = 4095;
}
InParser &operator>>(int &n)
{
char c;
while (!isdigit(c = read_ch()) && c != '-')
;
int sgn = 1;
if (c == '-')
{
n = 0;
sgn = -1;
}
else
{
n = c - '0';
}
while (isdigit(c = read_ch()))
{
n = 10 * n + c - '0';
}
n *= sgn;
return *this;
}
};
InParser f("cuplaj.in");
ofstream g("cuplaj.out");
// #define f cin
// #define g cout
const int nmax = 20009;
struct Box
{
struct Edge
{
int to, capacity, flow;
Edge *residual;
int remaining_capacity()
{
return capacity - flow;
}
} * edge;
};
int source, sink;
int n, boys, girls, visited[nmax], vtoken = 1, level[nmax], nexti[nmax];
vector<Box> v[nmax];
void get_graph();
bool bfs();
int dfs(int, int);
int get_max_flow();
int32_t main()
{
get_graph();
g << get_max_flow() << '\n';
// for (int i = 1; i <= boys; i++)
// for (int j = 0; j < (int)v[i].size(); j++)
// if (v[i][j].edge->capacity && v[i][j].edge->flow)
// g << i << " " << v[i][j].edge->to - boys << '\n';
return 0;
}
void get_graph()
{
int k;
f >> boys >> girls >> k;
n = boys + girls + 2;
source = n + 1;
sink = n + 2;
for (int i = 1; i <= boys; i++)
{
static Box to, xto;
to.edge = new Box::Edge;
to.edge->capacity = 1;
to.edge->flow = 0;
to.edge->to = i;
xto.edge = new Box::Edge;
xto.edge->capacity = 0;
xto.edge->flow = 0;
xto.edge->to = source;
to.edge->residual = xto.edge;
xto.edge->residual = to.edge;
v[source].push_back(to);
v[i].push_back(xto);
}
for (int i = 1; i <= girls; i++)
{
static Box to, xto;
to.edge = new Box::Edge;
to.edge->capacity = 1;
to.edge->flow = 0;
to.edge->to = sink;
xto.edge = new Box::Edge;
xto.edge->capacity = 0;
xto.edge->flow = 0;
xto.edge->to = i + boys;
to.edge->residual = xto.edge;
xto.edge->residual = to.edge;
v[i + boys].push_back(to);
v[sink].push_back(xto);
}
for (int x, y; k; k--)
{
f >> x >> y;
static Box to, xto;
to.edge = new Box::Edge;
to.edge->capacity = 1;
to.edge->flow = 0;
to.edge->to = y + boys;
xto.edge = new Box::Edge;
xto.edge->capacity = 0;
xto.edge->flow = 0;
xto.edge->to = x;
to.edge->residual = xto.edge;
xto.edge->residual = to.edge;
v[x].push_back(to);
v[y + boys].push_back(xto);
}
}
int get_max_flow()
{
int max_flow = 0;
while (bfs())
{
vtoken++;
memset(nexti, 0, sizeof nexti);
for (int minim = dfs(source, INT_MAX); minim; minim = dfs(source, INT_MAX))
max_flow += minim;
}
return max_flow;
}
bool bfs()
{
static queue<int> q;
visited[source] = vtoken;
level[source] = 1;
q.push(source);
while (!q.empty())
{
static int ac;
ac = q.front();
q.pop();
for (const Box &i : v[ac])
if (visited[i.edge->to] != vtoken && i.edge->remaining_capacity() > 0)
{
visited[i.edge->to] = vtoken;
level[i.edge->to] = level[ac] + 1;
q.push(i.edge->to);
}
}
return (visited[sink] == vtoken);
}
int dfs(int x, int minim)
{
if (x == sink)
return minim;
for (int cap, ne, ax; nexti[x] < (int)v[x].size(); nexti[x]++)
{
cap = v[x][nexti[x]].edge->remaining_capacity();
ne = v[x][nexti[x]].edge->to;
if (cap > 0 && level[ne] >= level[x])
{
ax = dfs(ne, min(cap, minim));
if (ax > 0)
{
Box::Edge *xe = v[x][nexti[x]].edge;
xe->flow += ax;
xe->residual->flow -= ax;
nexti[x]++;
return ax;
}
}
}
return 0;
}