Cod sursa(job #302841)

Utilizator SleepyOverlordPatcas Csaba SleepyOverlord Data 9 aprilie 2009 12:30:12
Problema Cuplaj maxim in graf bipartit Scor 90
Compilator cpp Status done
Runda Arhiva educationala Marime 2.95 kb
//Code by Patcas Csaba
//Time complexity: O(n*m^2)
//Space complexity: O(m+n)
//Method: Edmonds-Karp dupa capul meu numai pe liste de vecini
//Working time: 12:13- minutes

#include <stdio.h>
#include <vector>
#include <queue>

using namespace std;

#define in_file "cuplaj.in"
#define out_file "cuplaj.out"

#define VI vector <int>

#define FORN(i,n) for (int i=0;i<n;++i)
#define FOR(i,a,b) for (int i=a;i<=b;++i)
#define ALL(x) x.begin(), x.end()
#define PB push_back
#define S size()

#define inf 111111

struct Tedge
{
	int node,cap,f,inv;
};

int n,n1,n2,m,solution;
vector <vector <Tedge> > g, g2;
VI father, ind;

void bf()
{
	queue <int> l;
	l.push(0);
	father[0]=inf;
	while (!father[n] && !l.empty())
	{
		int node=l.front();
		FORN(i,g[node].S)
		{
			Tedge aux=g[node][i];
			if (!father[aux.node] && aux.cap>aux.f)
			{
				father[aux.node]=node;
				ind[aux.node]=i;
				l.push(aux.node);
			}
		}
		FORN(i,g2[node].S)
		{
			Tedge aux=g2[node][i];
			if (!father[aux.node] && aux.f)
			{
				father[aux.node]=-node;
				ind[aux.node]=i;
				l.push(aux.node);
			}
		}
		l.pop();
	}
}

int IncreaseFlow()
{
	int node=n, flow=inf;
	while (node!=0)
	{
		if (father[node]>=0)
		{
			Tedge aux=g[father[node]][ind[node]];
			flow=min(flow,aux.cap-aux.f);
		}
		else 
		{
			Tedge aux=g2[-father[node]][ind[node]];
			flow=min(flow,aux.f);
		}
		if (!flow) return 0;
		node=abs(father[node]);
	}
	node=n;
	while (node!=0)
	{
		if (father[node]>=0) 
		{
			g[father[node]][ind[node]].f+=flow;
			g2[node][g[father[node]][ind[node]].inv].f+=flow;
		}
		else 
		{
			g2[-father[node]][ind[node]].f-=flow;
			g[node][g2[-father[node]][ind[node]].inv].f-=flow;
		}
		node=abs(father[node]);
	}
	return flow;
}

void EdmondsKarp()
{
	father.resize(n+1);
	ind.resize(n+1);
	solution=0;
	while (1) 
	{
		fill(ALL(father),0);
		bf();
		if (father[n]) 
		{
			FORN(i,g2[n].S)
				if (father[g2[n][i].node] && g2[n][i].cap>g2[n][i].f)	
				{
					father[n]=g2[n][i].node;
					ind[n]=g2[n][i].inv;
					int aux=IncreaseFlow();
					solution+=aux;
				}
		}
		else break;
	}
}

void AddEdge(int node1, int node2, int c)
{
	Tedge aux;
	aux.node=node2;
	aux.cap=c;
	aux.f=0;
	g[node1].PB(aux);

	aux.node=node1;
	aux.cap=c;
	aux.f=0;
	aux.inv=g[node1].S-1;
	g2[node2].PB(aux);
	g[node1][g[node1].S-1].inv=g2[node2].S-1;
}

void BuildGraph()
{
	FOR(i,1,n1) AddEdge(0,i,1);
	FOR(i,n1+1,n1+n2) AddEdge(i,n,1);
}

int main()
{
	FILE* fin=fopen(in_file,"r");
	fscanf(fin,"%d%d%d",&n1,&n2,&m);
	n=n1+n2+1;
	g.resize(n+1);
	g2.resize(n+1);
	FORN(q,m)
	{
		int x,y;
		fscanf(fin,"%d%d",&x,&y);
		AddEdge(x,n1+y,1);
	}
	fclose(fin);

	BuildGraph();

	EdmondsKarp();

	FILE* fout=fopen(out_file,"w");
	fprintf(fout,"%d\n",solution);
	FOR(i,1,n1)
		FORN(j,g[i].S)
			if (g[i][j].cap=g[i][j].f) fprintf(fout,"%d %d\n",i,g[i][j].node-n1);
	fclose(fout);

	return 0;
}