Cod sursa(job #972666)

Utilizator bugyBogdan Vlad bugy Data 12 iulie 2013 13:03:44
Problema Algoritmul lui Dijkstra Scor 30
Compilator cpp Status done
Runda Arhiva educationala Marime 4.63 kb
#include <stdio.h>
#include <string.h>
#define oo 0x3f3f3f3f // < = > (1 << 30)
#define nmax 50005 
#define nmax2 250005
using namespace std;


class Heap
{ 
public:
    int *values;
    int *nodes;
    int *poz;
	int capVect;
	
	int dimVect, numere;
    Heap(int capVect);
	
    ~Heap();
 
    int parent(int poz);
 
    int leftSubtree(int poz);
 
    int rightSubtree(int poz);
 
    void pushUp(int poz1,int poz2);   
 
    void Insert_heap(int b,int x);

    int minim(int a,int b);

    void erase(int k);	
};

Heap::Heap(int capVect)
{
	this-> capVect = capVect;
	this->dimVect = -1;
	this->numere = -1;
	values = new int[capVect];	
	nodes = new int[capVect];	
	poz = new int[capVect];	
}

Heap::~Heap()
{
   delete[] values;
}

int Heap::parent(int poz)
{
    return (poz - 1) / 2;
}

int Heap::leftSubtree(int poz)
{
    if(poz * 2 +1 <= dimVect)
		return poz * 2 +1;
	else return -1;
}

int Heap::rightSubtree(int poz)
{
  	if(poz * 2 +2 <= dimVect)
		return poz * 2 +2;
	else return -1;
}

void Heap::pushUp(int poz1,int poz2)
{
int aux;
	aux = values[poz1];
	values[poz1] = values[poz2];
	values[poz2] = aux; 
	
	aux = nodes[poz1];
	nodes[poz1] = nodes[poz2];
	nodes[poz2] = aux; 
	
	aux = poz[poz1];
	poz[poz1] = poz[poz2];
	poz[poz2] = aux; 
}

void Heap::Insert_heap(int b,int x)
{
int poz_curent, poz_parinte;

    if(dimVect == -1)
	{
	values[0] = x;
	nodes[0] = b;
	poz[b] = 0;
	dimVect = 0;
	numere = 0;
	}
	else 
	{
	numere++;
	values[++dimVect] = x;
	nodes[dimVect] = b;
	poz[ b ] = dimVect; 
	
	poz_curent = dimVect;

	poz_parinte =  parent(poz_curent);
	while( values[ poz_parinte  ] > values[ poz_curent ] )
	{
		pushUp( poz_curent,  poz_parinte);
		poz_curent = poz_parinte;
		
		if(poz_curent == 0)
			break;
		poz_parinte =  parent(poz_curent);		
	}	
	}
}

int Heap::minim(int a, int b)
{
	if(values[a] < values[b]) return a;
	return b;   	
}

void Heap::erase(int k)
{
int poz_curent,aux,poz_stanga,poz_dreapta,fiu_cel_mare;
		
	if( k  != 0 )
	{
		k = poz[ k ];
	}

	aux = values[dimVect];
	values[dimVect] = values[k];
	values[k] = aux;
	
	aux = nodes[dimVect];
	nodes[dimVect] = nodes[k];
	nodes[k] = aux;
	
	aux = poz[dimVect];
	poz[dimVect] = poz[k];
	poz[k] = aux;

	dimVect--;
	poz_curent = k;

	poz_dreapta = rightSubtree(poz_curent);
	poz_stanga = leftSubtree(poz_curent);
	

	if(poz_dreapta < 0 && poz_stanga > 0)
		fiu_cel_mare = leftSubtree(poz_curent);
	else if(poz_dreapta > 0 && poz_stanga < 0)
		fiu_cel_mare = rightSubtree(poz_curent);
	else
		fiu_cel_mare = minim(poz_stanga,poz_dreapta);

	
	while( values[fiu_cel_mare] < values[poz_curent])
	{
		pushUp(fiu_cel_mare,poz_curent);
		poz_curent = fiu_cel_mare;

	poz_dreapta = rightSubtree(poz_curent);

	poz_stanga = leftSubtree(poz_curent);
	
	if(poz_dreapta < 0 && poz_stanga > 0)
		fiu_cel_mare = leftSubtree(poz_curent);
	else if(poz_dreapta > 0 && poz_stanga < 0)
		fiu_cel_mare = rightSubtree(poz_curent);
	else if(poz_dreapta > 0 && poz_stanga > 0)
		fiu_cel_mare = minim(poz_stanga,poz_dreapta);
	else break;
	}	
}


FILE *f = fopen("dijkstra.in","r"), *g = fopen("dijkstra.out","w");
int best[ nmax ], viz[ nmax ], M[ nmax ], length, n, m; 

struct graf
{
	int nod, cost;
	graf *next;	
};
graf *a[nmax];

void citire()
{
	int x, y, z;
	
	fscanf( f, "%d %d", &n, &m ); 
	
    for ( int i = 1; i <= m; ++i )
    {
        fscanf( f, "%d %d %d", &x, &y, &z);
		graf *q = new graf;
		q->nod = y;
		q->cost = z;
		q->next = a[x];
		a[ x ] = q;
    }
	fclose(f);
}

void dijkstra_heap( int start, int stop )
{
	graf *q, *p;
	Heap H(nmax2);
	memset(viz,0,sizeof(viz));
	memset(best,oo,sizeof(best));
	p = new graf;
	
	
	viz[ start ] = 1;
	best[ start ] = 0;
	M[ ++length ] = start;
	q = a[ start ];
	p->nod = start; 
	
	do
	{	
		//actualizam vecinii
		while ( q )
		{
			if ( best[ q->nod ] > q->cost + best[ p->nod ] )
			{
				if ( !viz[ q->nod ] )
				{
					H.Insert_heap( q->nod, q->cost + best[ p->nod ] );
					viz[ q->nod ] = 1;
				}
				else
				{
					H.erase(q->nod); 
					H.Insert_heap( q->nod,  q->cost + best[ p->nod ] );
				}
				best[ q->nod ] =  q->cost + best[ p->nod ] ;
			}	
			q = q -> next;
		}
		
	if( H.dimVect == -1 )
		break;
	p->cost = (int)H.values[0];
	p->nod = H.nodes[0];	
	H.erase(0);
	
	M[ ++length ] = p->nod;
	q = a[ p->nod ];
	}while ( 1 );
}

void afisare()
{
	//afisam lungimea unui drum minim de la nodul de start = 1 la nodul i+1.
	for ( int i = 2; i <= n; ++i )
	{
		if(best[ i ] == oo)
			fprintf( g,"0 ");
		else
		fprintf( g, "%d ",best[ i ] );
	}
	fprintf(g,"\n");
	fclose(g);
}
int main()
{
	citire();
	dijkstra_heap(1,n);
	afisare();
return 0;
}