Cod sursa(job #7058)

Utilizator m_dersidanDersidan Mihai m_dersidan Data 21 ianuarie 2007 12:14:40
Problema Radiatie Scor 30
Compilator cpp Status done
Runda preONI 2007, Runda 1, Clasele 11-12 Marime 2.79 kb
# include <stdio.h>

# define  _fin  "radiatie.in"
# define  _fout "radiatie.out"

# define  maxn  15002
# define  maxm  30002

# define  inf   1000000027

int n, m, k, p[maxm][2];
int *v[maxn], *c[maxn];		// muchia / costul

int mc[maxm][3];
int deg[maxn];

int d[maxn];				// distanta maxima minima pentru un drum


void readf()
{
	freopen(_fin, "r", stdin);
	int i, x, y, ct;
	
	for (scanf("%d%d%d", &n, &m, &k), i=1; i<=m; i++)
		 scanf("%d %d %d", &mc[i][0], &mc[i][1], &mc[i][2]),
		 ++deg[ mc[i][0] ], ++deg[ mc[i][1] ];
	
	for (i=1; i<=k; i++)
		 scanf("%d %d", &p[i][0], &p[i][1]);

	for (i=1; i<=n; i++)
		v[i] = new int[ deg[i]+1 ], v[i][0] = 0,
		c[i] = new int[ deg[i]+1 ];

	for (i=1; i<=m; i++)
		x=mc[i][0], y=mc[i][1], ct=mc[i][2],
		v[x][ ++v[x][0] ] = y, c[x][ v[x][0] ] = ct,
		v[y][ ++v[y][0] ] = x, c[y][ v[y][0] ] = ct;
}

// min-heap
// operatii cu heap-ul
int a[maxn], h[maxn];

inline int stanga(int x) { return x<<1; }
inline int dreapta(int x){ return (x<<1)|1; }
inline int parinte(int x){ return x>>1; }

void heapify(int i)
{
    int small;
    while ( 1 )
    {
        small = i;
        if ( stanga(i) <= a[0] && d[ a[stanga(i)] ] < d[ a[small] ] ) small = stanga(i);
        if ( dreapta(i)<= a[0] && d[ a[dreapta(i)]] < d[ a[small] ] ) small = dreapta(i);
        if ( small == i ) break;
        a[i] ^= a[small] ^= a[i] ^= a[small];
        h[a[i]] = i;
        h[a[small]] = small;
        i = small;
    }
}
void insert(int vf)
{
	int i = ++a[0];
    while ( i > 1 && d[vf] < d[a[parinte(i)]] )
    {
        a[i] = a[parinte(i)]; h[a[i]] = i;
        i = parinte(i);
    }
    a[i] = vf;
    h[vf] = i;
}
int getmin()
{
    if ( !a[0] ) return -1;
    int ret = a[1];
    a[1]    = a[ a[0]-- ];
    h[a[1]] = 1;
    heapify(1);
    return ret;
}
void deckey(int vf)
{
    int i = h[vf];
    while ( i > 1 && d[ a[parinte(i)] ] > d[ vf ] )
    {
        a[i] = a[parinte(i)]; h[a[i]] = i;
        i = parinte(i);
    }
    a[i] = vf; h[vf] = i;
}

inline int max(int a, int b) { return a>b?a:b; }

void relaxeaza(int w, int cost)
{
    if ( d[w] > cost ) // || d[w] == inf )
    {
        d[w] = cost;
        deckey(w);
    }
}

void pseudo_dijkstra(int s, int dest)
{
    int i, j, min, to, aux, mask;
    
    for(i=1; i<=n; i++) d[i] = inf, a[i]=i, h[i]=i;

	a[0] = n;
	
	d[s]=0;
	deckey(s);
	
    while ( (min=getmin())!=-1 )
    {
		if ( min == dest ) break;	// ok!!!
		
		for (j=1; j<=v[min][0]; j++)
			relaxeaza( v[min][j], max( d[min], c[min][j] ) );
    }
}

void solve()
{
	freopen(_fout, "w", stdout);

	for (int i=1; i<=k; i++)
	{
		pseudo_dijkstra( p[i][0], p[i][1] );
		printf("%d\n", d[ p[i][1] ] );
	}
}

int main()
{
	readf();
	solve();
	
	return 0;
}