Cod sursa(job #1574942)

Utilizator stoianmihailStoian Mihail stoianmihail Data 20 ianuarie 2016 22:37:57
Problema Radiatie Scor 60
Compilator c Status done
Runda Arhiva de probleme Marime 3.19 kb
#include <stdio.h>

#define Smerenie 30000
#define Nadejde 15001

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

typedef struct {
  int v, cost, next;
} list;

int N, M, Q;
cell edge[Smerenie]; // muchiile citite, sortate dupa cost.

/** Caracteristicile nodurilor. **/
int d[Nadejde];      // adancimea nodului "u".
int pay[Nadejde];    // costul muchiei (u, father[u]) din APM.
int boss[Nadejde];   // seful nodului "u".
int father[Nadejde]; // tatal nodului "u" in APM.

/** Reprezentare APM. **/
int buff;
int adj[Nadejde];     // capetele listelor de adiacenta.
list l[Nadejde << 1]; // lista muchiilor din APM.

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

/** Adauga-l pe "v" la lista de adiacenta a lui "u". **/
void addEdge(int u, int v, int cost) {
  l[++buff].v = v;
  l[buff].cost = cost;
  l[buff].next = adj[u];
  adj[u] = buff;
}

/** Sorteaza descrescator "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 padurile disjuncte. **/
void init() {
  int u;

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

/** Gaseste radacina nodului "u". **/
int find(int u) {
  int r, tmp;

  for (r = u; r != boss[r]; r = boss[r]);
  for (; u != boss[u]; u = tmp) {
    tmp = boss[u];
    boss[u] = r;
  }
  return r;
}

/** Arbore 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;
      addEdge(edge[i].u, edge[i].v, edge[i].cost);
      addEdge(edge[i].v, edge[i].u, edge[i].cost);
    }
  }
}

/** Exploreaza APM-ul. **/
void dfs(int u, int dad, int cost) {
  int pos;

  pay[u] = cost;
  father[u] = dad;
  d[u] = d[dad] + 1;
  for (pos = adj[u]; pos; pos = l[pos].next) {
    if (l[pos].v != dad) {
      dfs(l[pos].v, u, l[pos].cost);
    }
  }
}

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

  while (level--) {
    result = MAX(result, pay[*u]);
    (*u) = father[*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);
  }

  /* Calcularea solutiei. */
  apm();
  dfs(1, 0, 0);

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

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

    while (u != v) {
      result = MAX(result, MAX(pay[u], pay[v]));
      u = father[u];
      v = father[v];
    }
    fprintf(stdout, "%d\n", result);
  }
  fclose(f);
  fclose(stdout);

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