Cod sursa(job #6899)

Utilizator mugurelionutMugurel-Ionut Andreica mugurelionut Data 21 ianuarie 2007 10:37:45
Problema Radiatie Scor 90
Compilator cpp Status done
Runda preONI 2007, Runda 1, Clasele 11-12 Marime 3.01 kb
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <algorithm>
#include <vector>

using namespace std;

#define NMAX 15100
#define KMAX 15100
#define MMAX 32000
#define INF 1100000000

#define len(x) (ve[x].first)
#define c1(x) (ve[x].second.first)
#define c2(x) (ve[x].second.second)

vector<pair<int, pair<int, int> > > ve;
int* vp[4 * KMAX];
int nelem[4 * KMAX];
int peq[KMAX];

int tata[NMAX], h[NMAX], timpuni[NMAX], a[KMAX], b[KMAX], tuni[KMAX];
int i, j, l, k, N, M, K, cnt = 0;

inline int findt(int x, int tlim)
{
	int tx = x;

	while (tata[tx] != 0 && timpuni[tx] <= tlim)
		tx = tata[tx];

	return tx;
}

inline void uni(int x, int y)
{
	int tx, ty;

	tx = x;
	while (tata[tx] != 0)
		tx = tata[tx];

	ty = y;
	while (tata[ty] != 0)
		ty = tata[ty];

	if (tx != ty)
	{
		// union

		if (h[tx] < h[ty])
		{
			tata[tx] = ty;
			timpuni[tx] = k;
		}
		else
		if (h[tx] > h[ty])
		{
			tata[ty] = tx;
			timpuni[ty] = k;
		}
		else // h[tx] == h[ty]
		{
			tata[tx] = ty;
			timpuni[tx] = k;
			h[ty]++;
		}
	}
}

inline void binsrc(int tmin, int tmax, int cset)
{
	int p, np, s1 = -1, s2 = -1, t1, t2, neq = 0, ndif = 0;

	if (tmin > tmax)
		return;

	int tmid = (tmin + tmax) >> 1;

	np = nelem[cset];

	for (p = 0; p < np; p++)
	{
		t1 = findt(a[vp[cset][p]], tmid);
		t2 = findt(b[vp[cset][p]], tmid);

		if (t1 == t2)
		{
			neq++;
			tuni[vp[cset][p]] = tmid;
			peq[p] = 1;
		}
		else
		{
			ndif++;
			peq[p] = 0;
		}
	}

	if (ndif == 0)
		binsrc(tmin, tmid - 1, cset);
	else
	if (neq == 0)
		binsrc(tmid + 1, tmax, cset);
	else
	{
		s1 = ++cnt;

		vp[s1] = (int*) malloc(sizeof(int) * neq);
		nelem[s1] = 0;

		s2 = ++cnt;

		vp[s2] = (int*) malloc(sizeof(int) * ndif);
		nelem[s2] = 0;

		for (p = 0; p < np; p++)
			if (peq[p])
				vp[s1][nelem[s1]++] = vp[cset][p];
			else
				vp[s2][nelem[s2]++] = vp[cset][p];

		binsrc(tmin, tmid - 1, s1);
		binsrc(tmid + 1, tmax, s2);
	}
}

int main()
{
	freopen("radiatie.in", "r", stdin);

	scanf("%d %d %d", &N, &M, &K);

	ve.clear();

	for (k = 1; k <= M; k++)
	{
		scanf("%d %d %d", &i, &j, &l);
		ve.push_back(make_pair(l, make_pair(i, j)));
	}

	for (k = 1; k <= K; k++)
		scanf("%d %d", &a[k], &b[k]);

	// union by rank -> for connected components (also storing the time a union is made)

	sort(ve.begin(), ve.end());

	memset(tata, 0, sizeof(tata));
	memset(timpuni, 0, sizeof(timpuni));
	memset(h, 0, sizeof(h));

	for (k = 0; k < M; k++)
	{
		i = c1(k);
		j = c2(k);

		//fprintf(stderr, "%d %d -> %d\n", i, j, len(k));

		uni(i, j);
	}

	// do some binary search

	cnt = 0;

	vp[cnt] = (int *) malloc(sizeof(int) * K);
	nelem[cnt] = K;

	for (k = 1; k <= K; k++)
	{
		tuni[k] = M - 1;
		vp[cnt][k - 1] = k;
	}

	binsrc(0, M - 1, 0);

	freopen("radiatie.out", "w", stdout);

	for (k = 1; k <= K; k++)
	{
		if (a[k] == b[k])
			printf("0\n");
		else
			printf("%d\n", len(tuni[k]));
	}

	return 0;
}