Pagini recente » Cod sursa (job #2468587) | Cod sursa (job #2698597)
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
typedef signed long long ll;
typedef unsigned int uint;
typedef unsigned short ushort;
typedef unsigned char uchar;
template <typename T>
void printarray(T v[], uint n) {for(uint i = 0; i < n; i ++){cout << v[i] << " ";}cout << endl;}
template <typename T>
void printvector(vector<T> v){for (uint i = 0; i < v.size(); i ++){cout << v[i] << " ";}cout << endl;}
#define dbg(x) cout << #x " = " << x << " | ";
#define dbgnl(x) cout << #x " = " << x << endl;
const uint nmax = 10005;
const int INF = 2e9;
const char capacity = 1;
struct edge_t {
ushort node;
char flow, capacity;
list<edge_t>::iterator opposite;
};
typedef list<edge_t>::iterator edge_iter;
list<edge_t> G[nmax];
edge_iter parent_edge[nmax];
int maxflow = 0;
ushort n, m, e;
ushort source, dest;
bitset<nmax> visited;
#define A_NODE(i) (i)
#define B_NODE(i) (i+n)
void read() {
cin >> n >> m >> e;
source = 0;
dest = n + m + 1;
for (ushort i = 0; i < e; i++) {
ushort x, y;
cin >> x >> y;
G[A_NODE(x)].push_back({.node = B_NODE(y), .flow = 0, .capacity = 1});
G[B_NODE(y)].push_back({.node = A_NODE(x), .flow = 0, .capacity = 0});
// Link the edge going in the opposite direction
G[A_NODE(x)].back().opposite = next(G[B_NODE(y)].end(), -1);
G[B_NODE(y)].back().opposite = next(G[A_NODE(x)].end(), -1);
}
for (ushort i = 1; i <= n; i++) {
G[source].push_back({.node = A_NODE(i), .flow = 0, .capacity = 1});
G[A_NODE(i)].push_back({.node = source, .flow = 0, .capacity = 0});
G[source].back().opposite = next(G[A_NODE(i)].end(), -1);
G[A_NODE(i)].back().opposite = next(G[source].end(), -1);
}
for (ushort i = 1; i <= m; i++) {
G[B_NODE(i)].push_back({.node = dest, .flow = 0, .capacity = 1});
G[dest].push_back({.node = B_NODE(i), .flow = 0, .capacity = 0});
G[B_NODE(i)].back().opposite = next(G[dest].end(), -1);
G[dest].back().opposite = next(G[B_NODE(i)].end(), -1);
}
}
bool bfs() {
queue<ushort> q;
visited.reset();
q.push(source);
visited[source] = true;
while (!q.empty()) {
ushort node = q.front();
q.pop();
if (node == dest) break;
for (auto edge_it = G[node].begin(); edge_it != G[node].end(); ++edge_it) {
if (!visited[edge_it->node] && edge_it->flow < edge_it->capacity) {
visited[edge_it->node] = true;
q.push(edge_it->node);
parent_edge[edge_it->node] = edge_it;
}
}
}
if (visited[dest] == false) return false;
ushort cur_node = dest;
char minflow = CHAR_MAX;
while (cur_node != source) {
minflow = min(minflow, (char)(parent_edge[cur_node]->capacity - parent_edge[cur_node]->flow));
cur_node = parent_edge[cur_node]->opposite->node;
}
cur_node = dest;
while (cur_node != source) {
parent_edge[cur_node]->flow += minflow;
parent_edge[cur_node]->opposite->flow -= minflow;
cur_node = parent_edge[cur_node]->opposite->node;
}
maxflow += minflow;
return true;
}
void solve() {
while(bfs()) {}
}
void write() {
cout << maxflow << "\n";
}
int main() {
freopen("cuplaj.in", "r", stdin);
freopen("cuplaj.out", "w", stdout);
read();
solve();
write();
return 0;
}