Pagini recente » Cod sursa (job #2171863) | Cod sursa (job #211741) | Cod sursa (job #832920) | Cod sursa (job #366154) | Cod sursa (job #2961288)
#include <fstream>
#include <iostream>
#include <climits>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
ifstream fin("cuplaj.in");
ofstream fout("cuplaj.out");
struct edge{
int y;
int capacity;
int flow;
};
int n, m, x, y, e;
queue<int> q;
int father[20005];
vector<edge> ad[20005];
int source, destination;
bool explored[20005];
bool cmp(edge e1, edge e2) {
return e1.y < e2.y;
}
int bfs() {
fill(father + 1, father + n + m + 3, 0);
fill(explored + 1, explored + n + m + 3, 0);
explored[source] = 1;
q.push(source);
while(!q.empty()) {
int node = q.front();
q.pop();
if(node == destination)
continue;
for(auto vec : ad[node]) {
if(vec.flow < vec.capacity && explored[vec.y] == 0) {
explored[vec.y] = 1;
q.push(vec.y);
father[vec.y] = node;
}
}
}
if(explored[destination] == 0)
return 0; // destination can't be reached!
else
return 1; // destination reached!
}
int findPosition(int node, int vec){
if(ad[node].size() <= 50) {
for(int i = 0; i < ad[node].size(); i ++)
if(ad[node][i].y == vec)
return i;
} else {
int st = 0;
int dr = ad[node].size() - 1;
int mij;
while(st <= dr) {
mij = (st + dr) / 2;
if(ad[node][mij].y == vec)
return mij;
else if(ad[node][mij].y < vec)
st = mij + 1;
else if(ad[node][mij].y > vec)
dr = mij - 1;
}
}
return -1;
};
int main() {
fin >> n >> m >> e;
// pun muchiile citite in problema cu capacitate 1
for (int i = 1; i <= e; i++ )
{
fin >> x >> y;
ad[x].push_back({y + n, 1, 0});
ad[y + n].push_back({x, 0, 0});
}
source = n + m + 2; // aleg un nod sursa
destination = n + m + 1; // aleg un nod destinatie
// adaug muchii de capacitate 1 de la sursa la primul set de noduri
for(int i = 1 ; i <= n ; i++) {
ad[source].push_back({i, 1, 0});
ad[i].push_back({source, 0, 0});
}
// adaug muchii de capacitate 1 de la al doilea set de noduri la destinatie
for(int i = n + 1; i <= n + m; i ++) {
ad[i].push_back({destination, 1, 0});
ad[destination].push_back({i, 0, 0});
}
// sortez listele de adiacenta crescator
for(int i = 1 ; i <= n + m + 2; i ++)
sort(ad[i].begin(), ad[i].end(), cmp);
int max_flow = 0;
//return 0;
while(bfs()) {
//cout << "ceva" << '\n';
int min_flow = INT_MAX;
for(auto vec : ad[destination]) {
int pos = findPosition(vec.y, destination);
if (explored[vec.y] == 0 || ad[vec.y][pos].flow == ad[vec.y][pos].capacity)
continue;
int node = destination;
father[destination] = vec.y;
while (father[node] != 0) {
int pos1 = findPosition(father[node], node);
min_flow = min(min_flow, ad[father[node]][pos1].capacity - ad[father[node]][pos1].flow);
node = father[node];
}
node = destination;
max_flow += min_flow;
while (father[node] != 0) {
int pos1 = findPosition(father[node], node);
ad[father[node]][pos1].flow += min_flow;
int pos2 = findPosition(node, father[node]);
ad[node][pos2].flow -= min_flow;
node = father[node];
}
}
}
fout << max_flow << '\n';
for(int i = 1; i <= n ; i ++)
for(auto j : ad[i]) {
if(j.flow == 1)
fout << i << " " << j.y - n << '\n';
}
return 0;
}