Pagini recente » Cod sursa (job #2461224) | Cod sursa (job #2162160) | Cod sursa (job #2660195) | Cod sursa (job #296619) | Cod sursa (job #2961342)
#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
ifstream fin("cuplaj.in");
ofstream fout("cuplaj.out");
vector<pair<int, pair<long long int, int>>> towards[25000]; //nod, capacitate, pozitie
// lista de noduri care ajung la destinatie
vector<pair<int, int>> reach_dest;
vector<int> visited;
bool checked[25000];
pair<int, int> parent[25000];
int n, m, e, start, dest, curr_node, x, y;
int bfs()
{
queue<int> q;
visited.assign(dest + 1, 0);
q.push(start);
parent[start] = { -1, -1 };
while (!q.empty())
{
curr_node = q.front();
q.pop();
visited[curr_node] = 1;
if (curr_node == dest)
break;
for (int i = 0; i < towards[curr_node].size(); i++)
{
// daca nodul nu a fost vizitat si exista un drum valid
if (visited[towards[curr_node][i].first] == 0
&& towards[curr_node][i].second.first > 0)
{
// adaugam nodul in coada, il marcam ca vizitat si retinem tatal
q.push(towards[curr_node][i].first);
visited[towards[curr_node][i].first];
parent[towards[curr_node][i].first] = { curr_node, i };
}
}
}
return visited[dest]; // am ajuns sau nu la destinatie
}
int main()
{
fin >> n >> m >> e;
start = 0;
dest = n + m + 1;
for (int i = 1; i <= n; i++)
{
towards[start].push_back({ i, {1, 0} });
towards[i].push_back({ start, {0, 0} });
towards[i][towards[i].size() - 1].second.second = towards[start].size() - 1;
towards[start][towards[start].size() - 1].second.second = towards[i].size() - 1;
}
for (int i = 1; i <= e; i++)
{
fin >> x >> y;
towards[x].push_back({ n + y, {1, 0} });
towards[n + y].push_back({ x, {0, 0} });
checked[y] = true;
towards[y + n][towards[y + n].size() - 1].second.second = towards[x].size() - 1;
towards[x][towards[x].size() - 1].second.second = towards[y + n].size() - 1;
}
for (int i = 1; i <= m; i++)
{
if (checked[i])
{
towards[dest].push_back({ n + i, {0, 0} });
towards[n + i].push_back({ dest, {1, 0} });
reach_dest.push_back({ n + i, towards[n + i].size() - 1 });
towards[dest][towards[dest].size() - 1].second.second = towards[n + i].size() - 1;
towards[n + i][towards[n + i].size() - 1].second.second = towards[dest].size() - 1;
}
}
int flow = 0;
int position = 0;
pair<int, int> node;
while (bfs())
{
// parcurgem nodurile din care se poate ajunge la destinatie
for (auto item : reach_dest)
{
long long int mini = INT_MAX;
parent[dest] = item;
node = parent[dest];
int aux_dest = dest;
while (node.first != -1)
{
// calculam distanta
mini = min(mini, towards[node.first][node.second].second.first);
node = parent[node.first];
}
flow = flow + mini;
node = parent[dest];
// actualizam capacitatile
while (node.first != -1)
{
position = towards[node.first][node.second].second.second;
towards[node.first][node.second].second.first -= mini;
towards[aux_dest][position].second.first += mini;
aux_dest = node.first;
node = parent[node.first];
}
}
}
fout << flow << endl;
for (int i = 1; i <= n; i++)
{
for (int j = 0; j < towards[i].size(); j++)
{
if (towards[i][j].first && towards[i][j].second.first == 0)
{
fout << i << " " << towards[i][j].first - n << endl;
}
}
}
fout.close();
}
// spatiu: O(VE)
// timp: O(VE)