Cod sursa(job #255440)

Utilizator stocarulCosmin-Mihai Tutunaru stocarul Data 9 februarie 2009 19:20:57
Problema Flux maxim Scor 30
Compilator c Status done
Runda Arhiva educationala Marime 3.42 kb
#include<stdio.h>
#define infile "maxflow.in"
#define outfile "maxflow.out"
#define nmax 1001
#define mmax 5001
#define inf ~(1<<31)
int st=1,fi;
struct mat
	{
	int f,c; //fluxul si capacitatea
	} fc[nmax][nmax]; //matricea in care vom retine fluxul si capacitaea intre doua muchii
struct lista
	{
	int n,p; //nodul si pozitia
	} l[mmax],lt[mmax]; //lista normala...si lista grafului transpus
char viz[nmax]; //ca sa stim daca am mai vizitat nodul in parcurgerea respectiva sau nu
char b[nmax]; //aici marcam nodurile blocate (pe care sa nu le mai apelam...pt k le apelam degeaba...nu vor mai aduce imbunatatiri ;))
int p[nmax],pt[nmax]; //pozitiile din lsita a fiilor pt graful normal si pt graful transpus
int n; //numarul de noduri
int flux; //fluxul maxim al retelei de transport

int minim(int a, int b)
	{
	if(a<b) return a;
	return b;
	}

//adauga in lista grafului arcul (x,y)
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,m,x,y,z;
	scanf("%d %d\n",&n,&m); //citim numarul de noduri si numarul de muchii
	fi=n; //punctul de iesire din graf
	for(i=1;i<=m;i++)
		{
		scanf("%d %d %d\n",&x,&y,&z);
		fc[x][y].c=z; //capacitatea arcului (x,y)
		add(l,p,i,x,y); //graful normal
		add(lt,pt,i,y,x); //graful transpus
		}
	}

//parcurgerea in adancime pentru determinarea fluxului maxim
int dfs(int x, int f) //se poate ajunge la nodul x cu fluxul f
	{
	viz[x]=1; //marcam k l-am atins
	if(x==fi) { flux+=f; return 0; } //am ajuns la iesire...adaug la fluxul total...si returnez 0 (am folosit tot fluxul)
	int ul,y,c,cr;
	for(ul=p[x];ul&&f;ul=l[ul].p) //trecem pe la fiecare copil al lui x (in graful normal)
		if(!viz[l[ul].n]&&!b[l[ul].n]&&(fc[x][l[ul].n].c-fc[x][l[ul].n].f)>0) //daca nodul nu este deja vizitat in aceasta parcurgere, si daca acest arc nu este saturat
			{
			y=l[ul].n; //salvam nodul
			c=minim(f,fc[x][y].c-fc[x][y].f); //fluxul maxim cu care putem apela acest nod
			cr=dfs(y,c); //apelam nodul y, cu fluxul c
			viz[y]=0; //cand am apelat functia dfs, s-a vizitat nodul...acum il marcam ca nevizitat;))
			if(cr) b[y]=1; //s-a intors cu cost...acest nod nu va mai fi apelat
			fc[x][y].f+=(c-cr); //adaugam la fluxul acestui arc, fluxul folosit de nod
			f-=(c-cr); //scad din fluxul total fluxul folosi;))
			}
	//incercam parcurgerile in sens invers (destinatie-sursa)
	for(ul=pt[x];ul&&f;ul=lt[ul].p) //trecem pe la fiecare copil al lui x in graful transpus
		if(!viz[lt[ul].n]&&!b[lt[ul].n]&&fc[lt[ul].n][x].f) //daca nodul nu este deja viziat in parcurgerea asta, si daca avem flux;))
			{
			y=lt[ul].n; //salvam nodul
			c=minim(f,fc[y][x].f); //fluxul maxim cu care putem inainta ;))
			cr=dfs(y,c); //apelam nodul y cu fluxul c(este nod destinatie - sursa)
			//if(cr) b[y]=1; //s-a intors cu cost....acest nod nu va mai fi apelat
			viz[y]=0; //scaotem vizitarea
			fc[y][x].f-=(c-cr); //fiinda am parcurs arcul in sens invers....voi scade fluxul folosit din cel total
			f-=(c-cr); //scadem din fluxul total pe cel folosit
			}
	return f; //returnam fluxul ramas
	}

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

citire(); //citim datele din fisier...si salvam graful normal si graful transpus in memorie
dfs(st,inf); //parcurgem din nodul de start....cu capacitate infinita
printf("%d",flux); //afisem fluxul maxim al retelei

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