Pagini recente » Cod sursa (job #2479477) | Cod sursa (job #2919843) | Cod sursa (job #2595993) | Cod sursa (job #2646128) | Cod sursa (job #2962750)
#include <fstream>
#include <vector>
#include <queue>
#include <bitset>
using namespace std;
ifstream fin("cuplaj.in");
ofstream fout("cuplaj.out");
struct Edge {
int x, y, cap, poz;
};
int n, m, e, s, d, x, y;
vector <Edge> edges;
vector <vector<int>> graph;
vector <int> t;
bitset<20010> visited;
bool bfs() {
visited.reset();
queue <int> q;
q.push(s);
visited[s] = true;
int node;
while(!q.empty()) {
node = q.front();
q.pop();
if(node == d)
continue;
for(auto it : graph[node]) {
Edge edge = edges[it];
if(!visited[edge.y] && edge.cap) {
t[edge.y] = it;
visited[edge.y] = true;
q.push(edge.y);
}
}
}
return visited[d];
}
// algoritmul lui Edmonds-Karp pentru flux maxim
int getMaxFlow() {
int answer = 0;
while(bfs()) {
for(auto it : graph[d]) {
if(!visited[edges[it].y])
continue;
Edge edge = edges[it];
t[d] = edge.poz;
int minFlow = 2e9;
for (int node = d; node != s; node = edges[t[node]].x) {
if (edges[t[node]].cap < minFlow)
minFlow = edges[t[node]].cap;
}
if(minFlow == 0)
continue;
answer += minFlow;
for (int node = d; node != s; node = edges[t[node]].x) {
edges[t[node]].cap -= minFlow;
edges[edges[t[node]].poz].cap += minFlow;
}
}
}
return answer; // fluxul maxim = cuplajul maxim
}
int main() {
fin >> n >> m >> e;
d = n + m + 1;
graph = vector <vector<int>> (n + m + 2);
t = vector <int> (n + m + 2);
// adaugam muchiile de la nodurile din stanga la cele din dreapta
for(int i = 1; i <= e; i ++) {
fin >> x >> y;
int dim = edges.size();
graph[x].push_back(dim);
graph[y + n].push_back(dim + 1);
edges.push_back({x, y + n, 1, dim + 1});
edges.push_back({y + n, x, 0, dim});
}
// adaugam muchiile de la sursa la nodurile din stanga
for(int i = 1; i <= n; i ++) {
int dim = edges.size();
graph[s].push_back(dim);
graph[i].push_back(dim + 1);
edges.push_back({s, i, 1, dim + 1});
edges.push_back({i, s, 0, dim});
}
// adaugam muchiile de la nodurile din dreapta la destinatie
for(int i = n + 1; i <= n + m; i ++) {
int edges_cnt = edges.size();
graph[i].push_back(edges_cnt);
graph[d].push_back(edges_cnt + 1);
edges.push_back({i, d, 1, edges_cnt + 1});
edges.push_back({d, i, 0, edges_cnt});
}
fout << getMaxFlow() << '\n';
// afisam muchiile care fac parte din cuplaj = muchiile saturate
for(auto edge : edges)
if(edge.x < edge.y && edge.x != s && edge.y != d && edge.cap == 0)
fout << edge.x << " " << edge.y - n << '\n';
return 0;
}