Cod sursa(job #1709462)

Utilizator TeamFIIDUAIC backtrackers TeamFIID Data 28 mai 2016 12:24:13
Problema Metrou4 Scor 0
Compilator cpp Status done
Runda ONIS 2016 - Runda - 2 - ACM ICPC Romanian Programming Contest Marime 2.67 kb
#include <cstdio>
#include <queue>
#include <iostream>
#define NMAX 150001
#define INF 1<<30
using namespace std;
int T,N;
struct punct
{
	int x, y;
}P[NMAX];
int H[NMAX],heap_size; // retin heap-ul
int poz[NMAX]; // retin pozitia din heap a punctului i
int cmin[NMAX],total; //costul minim pentru i;
bool uz[NMAX];
//priority_queue <pair<int, int> > pq;
int dist(int i, int j);
void reset();
void apm();
void make_heap();
void scufunda(int i);
void promote(int i);
int scoate();
int modul(int x)
{
	if (x < 0) return -x;
	return x;
}
int main()
{
	freopen("metrou4.in", "r", stdin);
	freopen("metrou4.out", "w", stdout);
	cin >> T;
	int test; int i;
	for (test = 0; test < T; test++)
	{
		cin >> N;
		reset();
		for (i = 1; i <= N; i++)
			cin >> P[i].x >> P[i].y;
		apm();
		cout << total << '\n';
	}
	return 0;
}
void apm()
{
	int i;
	uz[1] = 1;
	H[1] = 1;
	poz[1] = 1;
	for (i = 2; i <= N; i++)
	{
		H[i-1] = i;
		cmin[i] = dist(1, i);
		poz[i] = i;
	}
	heap_size = N - 1;
	make_heap();
	int nr = 2;
	for (nr = 2; nr <= N; nr++)
	{
		int vecin = scoate();
		uz[vecin] = 1;
		total += cmin[vecin];
		for (i = 1; i <= N; i++)
		{
			if (!uz[i] && cmin[i] > dist(vecin, i))
			{
				cmin[i] = dist(vecin, i);
				promote(poz[i]); //promoveaza din pozitia din heap de pe care se afla nodul i
			}
		}
	}
}
int dist(int i, int j)
{
	int d = 0;
	d = modul(P[i].x - P[j].x) + modul(P[i].y - P[j].y);
	return d;
}
void reset()
{
	int i;
	for (i = 1; i <= N; i++)
	{
		cmin[i] = INF;
		uz[i] = 0;
	}
	total = 0;
}
void make_heap()
{
	int i;
	for (i = heap_size / 2; i >= 1; i--)
		scufunda(i);
}
void scufunda(int i)
{
	//scufund nodul i;
	while (1)
	{
		int fiu = 2 * i;
		if (fiu < heap_size && cmin[H[fiu + 1]] < cmin[H[fiu]])
			fiu++;
		if (fiu > heap_size) return;
		//in fiu am fiul minim acum, pe el trebuie sa il pun;
		if (cmin[H[i]] > cmin[H[fiu]])
		{
			swap(poz[H[i]], poz[H[fiu]]); //interschimb pozitiile pe care se gasesc in heap
			swap(H[i], H[fiu]);// interschimb nodurile din heap
			i = fiu;
		}
		else return;
	}
}
int scoate()
{
	//returneaza nodul cel mai apropiat de apm
	int nod = H[1];
	poz[H[heap_size]] = 1;
	poz[nod] = -1; 
	swap(H[1], H[heap_size]);
	heap_size--;
	scufunda(1);
	return nod;
}
void promote(int i)
{
	//urca nodul de pe pozitia i din heap;
	while (1)
	{
		int tata = i / 2;
		if (tata < 1)
			return;
		if (cmin[H[tata]] > cmin[H[i]])
		{
			//trebuie sa le interchimb;
			swap(poz[H[tata]], poz[H[i]]); //interschimb pozitiile pe care se gasesc in heap
			swap(H[i], H[tata]);// interschimb nodurile din heap
			i = tata;
		}
		else
			return;
	}

}