Cod sursa(job #1574840)

Utilizator stoianmihailStoian Mihail stoianmihail Data 20 ianuarie 2016 21:28:27
Problema Radiatie Scor 100
Compilator c Status done
Runda Arhiva de probleme Marime 2.74 kb
#include <stdio.h>

#define Smerenie 30000
#define Nadejde 15000
#define NIL -1

typedef struct {
  int u, v, cost;
} cell;

int N, M, Q;
int d[Nadejde + 1];      // d[u] este adancimea nodului u.
cell edge[Smerenie];     // retinem muchiile citite.
int pay[Nadejde + 1];    // pay[u] este costul de pe muchia (u, boss[u]).
int boss[Nadejde + 1];   // boss[u] este tatal lui u.

/** max(X, Y). **/
int MAX(int X, int Y) {
  return X > Y ? X : Y;
}

/** Sorteaza crescator "edge". **/
void sort(int begin, int end) {
  int b = begin, e = end;
  int pivot = edge[(b + e) >> 1].cost;

  while (b <= e) {
    while (edge[b].cost < pivot) {
      b++;
    }
    while (edge[e].cost > pivot) {
      e--;
    }
    if (b <= e) {
      cell tmp = edge[b];
      edge[b++] = edge[e];
      edge[e--] = tmp;
    }
  }
  if (begin < e) {
    sort(begin, e);
  }
  if (b < end) {
    sort(b, end);
  }
}

/** Initializeaza componentele conexe. **/
void init() {
  int u;

  for (u = 1; u <= N; u++) {
    boss[u] = u;
    d[u] = NIL;
  }
}

/** Gaseste radacina nodului "u". **/
int find(int u) {
  for (; u != boss[u]; u = boss[u]);
  return u;
}

/** Construieste arborele partial de cost minim. **/
void apm() {
  int i, ru, rv;

  init();
  sort(0, M - 1);
  for (i = 0; i < M; i++) {
    ru = find(edge[i].u);
    rv = find(edge[i].v);

    if (ru != rv) {
      boss[rv] = ru;
      pay[rv] = edge[i].cost;
    }
  }
}

/** Determina adancimea fiecarui nod. **/
void dfs(int u) {
  if (d[u] != NIL) {
    return;
  }

  if (u == boss[u]) {
    d[u] = 1;
  } else {
    dfs(boss[u]);
    d[u] = d[boss[u]] + 1;
  }
}

/** Urca nodul "u" cu "level" nivele. **/
int climb(int *u, int level) {
  int result = 0;

  while (level--) {
    result = MAX(result, pay[*u]);
    (*u) = boss[*u];
  }
  return result;
}

int main(void) {
  int i, u, v, diff, result;
  FILE *f = fopen("radiatie.in", "r");

  /* Citirea datelor. */
  fscanf(f, "%d %d %d", &N, &M, &Q);
  for (i = 0; i < M; i++) {
    fscanf(f, "%d %d %d", &edge[i].u, &edge[i].v, &edge[i].cost);
  }

  /* Construim arborele partial de cost minim. */
  apm();

  /* Aflam adancimea fiecarui nod. */
  for (u = 1; u <= N; u++) {
    dfs(u);
  }

  /* Raspunde la intrebari. */
  freopen("radiatie.out", "w", stdout);
  while (Q--) {
    fscanf(f, "%d %d", &u, &v);

    /* Adu nodurile la acelasi nivel. */
    diff = d[u] - d[v];
    if (diff < 0) {
      result = climb(&v, -diff);
    } else {
      result = climb(&u, diff);
    }

    /* Calculeaza costul maxim de pe muchii, pana la lca(u, v). */
    while (u != v) {
      result = MAX(result, MAX(pay[u], pay[v]));
      u = boss[u];
      v = boss[v];
    }
    fprintf(stdout, "%d\n", result);
  }
  fclose(f);
  fclose(stdout);

  /// Multumim Doamne!
  puts("Doamne ajuta!");
  return 0;
}