Cod sursa(job #3190698)

Utilizator daria_lapadusLapadus Daria daria_lapadus Data 7 ianuarie 2024 20:32:30
Problema Cc Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.52 kb
#include<stdio.h>
#define Nm 101
#define Inf Nm*10000

int D[Nm][Nm],n;        // D este matricea de distante, n este numarul de concurenti/calculatoare
int F[2*Nm][2*Nm],Q[4*Nm*Nm],Dm[2*Nm],Pre[2*Nm],Uz[2*Nm],cost; // Variabile si matrici auxiliare pentru algoritm

void read()
{
    int i,j;

    freopen("cc.in","r",stdin); // Deschid fișierul "cc.in" pentru citire
    scanf("%d",&n);             // Citesc numarul de concurenti/calculatoare
    for(i=1;i<=n;i++)           // Citesc matricea de distante
	for(j=1;j<=n;j++)
	    scanf("%d",&D[i][j]);  // Citesc fiecare element al matricei de distante
}

void insert(int x, int &r)
{
    if(!Uz[x])               // Verific daca x nu a fost folosit (Uz[x] este 0)
    {
	Q[++r]=x;             // Adaug x in coada Q si incrementez r
	Uz[x]=1;             // Marchez x ca folosit
    }
}

int Bellman_Ford()
{
    int l=0,r=-1,x,i;

    for(i=1;i<=2*n+1;i++)    // Initializez distantele si folosirea nodurilor
    {
	Dm[i]=Inf;
	Uz[i]=0;
    }
    for(i=1;i<=n;i++)        // Pun nodurile neasociate in coada
	if(!F[0][i])
	{
	    Dm[i]=0;
	    Pre[i]=0;
	    insert(i,r);
	}

    // Algoritmul Bellman-Ford
    while(l<=r)
    {
	x=Q[l++];            // Scot un element din coada Q
	Uz[x]=0;             // Marchez nodul ca nefolosit
	// Parcurg vecinii nodului x si actualizez distantele si predecesorii
	if(x>n)
	{
	    for(i=1;i<=n;i++)
		if(F[x][i]<0 && Dm[x]-D[i][x-n]<Dm[i])
		{
		    Dm[i]=Dm[x]-D[i][x-n];
		    Pre[i]=x;
		    insert(i,r);
		}
	    if(!F[x][2*n+1] && Dm[x]<Dm[2*n+1])
	    {
		Dm[2*n+1]=Dm[x];
		Pre[2*n+1]=x;
	    }
	}
	else
	    for(i=n+1;i<=2*n;i++)
		if(!F[x][i] && Dm[x]+D[x][i-n]<Dm[i])
		{
		    Dm[i]=Dm[x]+D[x][i-n];
		    Pre[i]=x;
		    insert(i,r);
		}
    }

    return Dm[2*n+1];       // Returnez distanta minima la nodul final
}

void solve()
{
    int i,j;

    for(j=0;j<n;j++)        // Repet algoritmul pentru fiecare concurent
    {
	cost+=Bellman_Ford(); // Calculez costul minim si actualizez costul total
	i=2*n+1;
	while(i)              // Actualizez fluxul pe baza predecesorilor
	{
	    F[Pre[i]][i]++;
	    F[i][Pre[i]]--;
	    i=Pre[i];
	}
    }
}

void write()
{
    freopen("cc.out","w",stdout); // Deschid fisierul "cc.out" pentru scriere
    printf("%d\n",cost);          // Scriu costul total in fisier
}

int main()
{
    read();       // Citesc datele de intrare
    solve();      // Rezolv problema
    write();      // Scriu rezultatul
    return 0;
}