Cod sursa(job #255650)

Utilizator stocarulCosmin-Mihai Tutunaru stocarul Data 10 februarie 2009 09:42:49
Problema Cuplaj maxim in graf bipartit Scor 0
Compilator c Status done
Runda Arhiva educationala Marime 2.65 kb
#include<stdio.h>
#define infile "cuplaj.in"
#define outfuile "cuplaj.out"
#define nmax (20*1000+5)
#define mmax (nmax+100*1000+1)
#define inf ~(1<<31)
struct lista
	{
	int n,p,f; //nodul pozitia si fluxul folosit pe acest arc
	} l[mmax],lt[mmax]; //lista pt graful normal si pt graful transpus
char viz[nmax]; //vector pt vizite
int p[nmax],pt[nmax]; //pozitiile din lista pt graful normal si pt cel transpus
int l,r; //lungimea celor doua grupuri de noduri
int m; //numarul de muchii
int st,fi; //cele doua noduri pe care le adaugam a.i. sa avem o retea
int flux; //fluxul maxim din cuplaj

//adauga arcul (x,y) in lista
void add(struct lista l[mmax], int p[nmax], int m, int x, int y)
	{
	l[m].n=y; l[m].p=p[x]; p[x]=m;
	}

void citire()
	{
	int i,x,y;
	scanf("%d %d %d\n",&l,&r,&m); //nuymarul nodurilor din fiecare grupa, si numarul de muchii dintre noduri
	for(i=1;i<=m;i++) //fiecare muchie in parte
		{
		scanf("%d %d\n",&x,&y);
		y+=l; //numerotarea nodurilor din grupa 2 incepe de la l
		add(l,p,i,x,y) //graful normal
		add(lt,pt,i,y,x) //graful transpus
		}
	}

//transformam graful intr-o retea de transport
void initializare()
	{
	int i;
	st=l+r+1; fi=st+1; //nuymarul de ordine al celor doua noduri (start si final)
	for(i=1;i<=l;i++) //trebuie sa adaugam arc de la nodul de start la toate nodurile din grupa l
		{
		++m;
		add(l,p,m,st,i); //adaugam in graful normal
		add(lt,pt,m,i,st); //adaugam in graful transpus
		}
	for(i=1;i<=r;i++)//trebuie sa adaugam arc de la fiecare nod din grupa a 2-a la nodul final
		{
		++m;
		add(l,p,m,i,fi); //graful normal
		add(lt,p,m,fi,i); //graful transpus
		}
	}

//apelam un nod (cu fluxul f)....si returnam fluxul nefolosit de nod
int dfs(int x, int f)
	{
	viz[x]=1; //marcam ca vizitat nodul x
	if(x==fi) { flux+=f; return 0; } //am atins finalul...salvam fluxul si returnam 0
	int ul,c;
	for(ul=p[x];ul&&f;ul=l[ul].p) //parcurgem copii lui x
		if(!viz[l[ul].n]&&!l[ul].f) //daca n-am mai vizitat nodul, si daca arcul nu este satura (fluxul este 0)
			{
			c=dfs(l[ul].n,1); //apelam nodul cu fluxul 1
			viz[l[ul].n]=0; //devizitam nodul
			if(!c)
				{
				l[ul].f=1; //saturam arcul
				f-=1; //scadem ca am folosit din flux
				}
			}
	return f; //returnam fluxul nefolosit
	}

void  afisare()
	{
	printf("%d\n",flux); //afisem fluxul maxim
	}

int main()
{
freopen(infile,"r",stdin);
freopen(outfile,"w",stdout);

citire(); //citim graful
initializare(); //transformam graful in retea de transport
dfs(st,inf); //parcurgem reteaua din nodul de start cu flux infinit...si aflam fluxul total
afisare(); //afisem

fclose(stdin);
fclose(stdout);
return 0;
}