Cod sursa(job #147534)

Utilizator anna_bozianuBozianu Ana anna_bozianu Data 3 martie 2008 09:37:46
Problema Critice Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.61 kb
#include<stdio.h>
void citire();
void flux();
void conex1();
void conex2();
void afisare();
long path();
long n,m,grad[1001],x[10001],y[10001],
cp[1001][1001],fl[1001][1001],*vec[1001],dad[1001],coada[1001];
int main()
{
	citire();
	flux();//algoritmul lui Dinic
	conex1();//noduri conectate la sursa in reteaua reziduala
	conex2();//noduri conectate la destinatie in reteaua reziduala
	afisare();
	return 0;
}
void citire()
{       long i,xx,yy,cc;
	FILE *f=fopen("critice.in","r");
	fscanf(f,"%ld%ld",&n,&m);//n=nr varfuri;m=nr muchii;
	for(i=1;i<=m;i++)
	{ fscanf(f,"%ld%ld%ld",&xx,&yy,&cc);
	  grad[xx]++;grad[yy]++;x[i]=xx;y[i]=yy;
	  cp[xx][yy]=cp[yy][xx]=cc;
	}//citire muchii si capacitati;calcul grade varfuri;
	for(i=1;i<=n;i++)
	{ vec[i]=new long [grad[i]+2];
	  vec[i][grad[i]+1]=0;
	  grad[i]=0;
	}//alocare spatiu pt lista vecini;
	for(i=1;i<=m;i++)
	{ vec[x[i]][++grad[x[i]]]=y[i];
	  vec[y[i]][++grad[y[i]]]=x[i];
	}//creare lista vecini
	fclose(f);
}
void flux()
{       long i,fl_drum,j;
	while(path())
	{  for(i=1;i<=n;i++)
	   { if(!dad[i])continue;
	     if(cp[i][n]<=fl[i][n])continue;
	     //se alege un nod numai daca exista un drum minim
	     //sursa->....->nod->destinatie
	     //deci drum de lungime minima. astfel la o aplicare
	     //a unui pas se vor satura toate drumurile minime
	     fl_drum=cp[i][n]-fl[i][n];
	     for(j=i;j!=1;j=dad[j])
	      if(fl_drum>cp[dad[j]][j]-fl[dad[j]][j]);
	       fl_drum=cp[dad[j]][j]-fl[dad[j]][j];
	     //calculeaza fluxul pe drumul minim ales
	     if(!fl_drum)continue;
	     //drumul a fost deja saturat-sari peste
	     //altfel se satureaza drumul respectiv
	     fl[i][n]+=fl_drum;fl[n][i]-=fl_drum;
	     for(j=i;j!=1;j=dad[j])
	     { fl[dad[j]][j]+=fl_drum;
	       fl[j][dad[j]]-=fl_drum;
	     }
	   }
	}
}
long path()
//cauta drum minim sursa->destinatie in reteaua reziduala prin BFS
{
	long i,ii,jj,nv,first,last;
	for(i=2;i<=n;i++) dad[i]=0;dad[1]=-1;
	//reinitializare vector de predecesori
	first=last=1;coada[first]=1;
	//initializare coada cu sursa=1
	while(first<=last)
	{ ii=coada[first];//nod curent = primul nod din coada
	  nv=grad[ii];
	  for(i=1;i<=nv;i++)
	  { jj=vec[ii][i];
	    if(dad[jj])continue;
	    //daca vecin intrat in coada sari peste
	    if(cp[ii][jj]<=fl[ii][jj])continue;
	    //daca vecin fals in reteaua reziduala sari peste
	    dad[jj]=ii;
	    //predecesor vecin = nod curent
	    last++;coada[last]=jj;
	    //vecin intra in coada
	    if(jj==n)return 1;
	    // daca destinatia a intrat in coada am gasit drumul
	  }//parcurgere vecini nod curent
	}//parcurgerea in latime (BFS)
	return 0;//daca destinatia nu a fost atinsa nu exista drum
}
void conex1()
{       long i,first,last,ii,jj,nv;
	for(i=1;i<=n;i++)dad[i]=0;dad[1]=1;
	first=1;last=1;coada[1]=1;
	while(first<=last)
	{ ii=coada[first];
	  nv=grad[ii];
	  for(i=1;i<=nv;i++)
	  { jj=vec[ii][i];
	    if(dad[jj])continue;
	    if(cp[ii][jj]<=fl[ii][jj])continue;
	    coada[++last]=jj;
	    dad[jj]=1;
	  }
	}
}
void conex2()
{       long i,first,last,ii,jj,nv;
	for(i=1;i<=n;i++)dad[i]=0;dad[n]=2;
	first=1;last=1;coada[1]=n;
	while(first<=last)
	{ ii=coada[first];
	  nv=grad[ii];
	  for(i=1;i<=nv;i++)
	  { jj=vec[ii][i];
	    if(dad[jj])continue;
	    if(cp[jj][ii]<=fl[jj][ii])continue;
	    coada[++last]=jj;
	    dad[jj]=2;
	  }
	}
}
void afisare()
{       long i,sol=0;
	FILE *f=fopen("critice.out","w");
	for(i=1;i<=m;i++)
	 if(dad[x[i]]+dad[y[i]]==3)sol++;
	fprintf(f,"%ld\n",sol);
	for(i=1;i<=m;i++)
	 if(dad[x[i]]+dad[y[i]]==3)
	  fprintf(f,"%ld ",i);
	fclose(f);
}