Pagini recente » Cod sursa (job #837571) | Cod sursa (job #2694898) | Cod sursa (job #1240741) | Cod sursa (job #2201579) | Cod sursa (job #2963379)
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#define INF 1024
using namespace std;
ifstream f("harta.in");
ofstream g("harta.out");
//const int INF=1024;
//int maxim=INF;
vector<int> intrare;
vector<int>iesire;
vector<int>dist;
int n, plecare, destinatie;
struct muchie {
int nod, vec, flux, cap;
};
vector<muchie> v[INF]; //va fi graful generat, in el punem fluxul
muchie tata[INF];
queue<int> q;
vector<muchie> drum;
bool BF()
{
for(int i=1;i<=n*2+2;i++)
{
dist[i]=INF;
tata[i]={0,0,0};
}
dist[plecare] = 0;
q.push(plecare);
while(!q.empty())
{
int nod= q.front();
q.pop();
for(auto i : v[nod])
{
if(dist[i.vec] > dist[nod] + 1 && i.flux < i.cap) //putem trimite flux pe aici
{
dist[i.vec] = dist[nod] +1;
tata[i.vec] =i;
q.push(i.vec);
}
}
}
if(dist[destinatie] != INF)
return 1;
return 0;
}
int main()
{
dist.resize(INF);
intrare.resize(INF);
iesire.resize(INF);
f>>n;
//1..n nodurile de pe partea stanga
//n+1, n+2,....2n nodurile de pe partea dreapta
//2n+1 - plecare, 2n+2 - destinatie
plecare = 2*n+1;
destinatie = 2*n+2;
int rezultat = 0,x,y;
for(int i=1;i<=n;i++)
{
f>>x>>y;
iesire[i]=x; intrare[y]=x;
//tragem liniile 0->i, (n+i)-> 2n+1
v[plecare].push_back({plecare,i,0,iesire[i]});
v[i].push_back({i,plecare,0,0});
v[n+i].push_back({n+i, destinatie,0,intrare[i]});
v[destinatie].push_back({destinatie,n+i,0,0});
rezultat =rezultat+ iesire[i];
}
for(int i=1;i<=n;i++)
{
for(int j=n+1; j<=2*n;j++)
if(i+n !=j)
//tragem muchiile (x,y) de capacitate 1 unde x,y sunt diferite
{
v[i].push_back({i,j,0,1});
v[j].push_back({j,i,0,0});
}
}
while(BF()) //cat timp gasim un drum de la 1 la n
{
int d= destinatie;
drum.clear();
while(tata[d].nod!=0)
{
drum.push_back(tata[d]);
d=tata[d].nod;
}
int max= INF; // fluxul maxim pe care il pot trimite pe drumul gasit
for(auto i:drum) //calculam ce flux poate fi trimis
max = min(max, i.cap - i.flux);
for(auto m: drum) //scadem si adunam fluxul pe care il bagam din toate muchiile
{
x= m.nod; y=m.vec;
for(int i=0;i< v[x].size();i++) //gasim muchia (x,y) si adunam fluxul gasit
if(v[x][i].vec == y)
{
v[x][i].flux+=max;
break;
}
for(int i=0;i<v[y].size();i++) //gasim muchia (y,x) si scad fluxul bagat
if(v[y][i].vec==x)
{
v[y][i].flux-=max;
break;
}
}
}
g<<rezultat<<endl;
for(int i=1;i<=n;i++)
for(auto j: v[i])
if(j.flux > 0)
g<<j.nod<<" "<<j.vec-n<<endl;
return 0;
}
//complexitate: O(E*F) e-> nr de noduri, f-> flow-ul maxim
//Codul prezentat este alg lui Ford-Fulkerson pentru a gasi flow-ul maxim
//intr-un graf. Fiecare nod are o capacitate. Incepe cu un flow initial si
//cauta de repetate ori un drum cat mai bun. Augmenteaza drumul curent pana
//cand nu mai poate
// vector<muchie> v[inf] este graful cu fluxul, initial va fi 0
//muchie tata[inf] retine parintele fiecarui nod in drum
//q pt BFS
//vector<muchie> drum este vectorul care imi retine nodurile din drum
//bool BF este parcurgerea BFS
//in functia main vom apela BFS si vom updata graful in functie de flow-ul
//maxim gasit.