Wednesday, January 11, 2017

UVa 12238 - Ants Colony

Accepted date: 2017-01-11
Run Time: 0.330
Ranking (as of 2016-01-11): 31 out of 359
Language: C++

For explanation, see Range Minimum Query and Lowest Common Ancestor - topcoder.


/*
  UVa 12238 - Ants Colony

  To build using Visual Studio 2012:
    cl -EHsc -O2 UVa_12238_Ants_Colony.cpp
*/

#include <algorithm>
#include <vector>
#include <cstdio>
#ifdef __ELAPSED_TIME__
#include <ctime>
#endif
using namespace std;

const int N_max = 100000;

struct edge {
  int v_;
  int weight_;
  edge(int v, int weight) : v_(v), weight_(weight) {}
};

vector<edge> edges[N_max];

const int level_max = 17; // ceil(log2(N_max))
int levels[N_max]; // level (depth) of node i in the tree
long long weights[N_max]; // weights[i] is the total length from the root to i-th node
int parents[N_max]; // parent node of i
int ancestors[N_max][level_max + 1];
  // ancestors[i][j] is the 2^j-th ancestor of node i

void dfs(int u, int parent, int level)
{
  levels[u] = level;
  const vector<edge>& mes = edges[u];
  for (size_t i = 0; i < mes.size(); i++) {
    int v = mes[i].v_, w = mes[i].weight_;
    if (v != parent) {
      parents[v] = u, weights[v] = w + weights[u];
      dfs(v, u, level + 1);
    }
  }
}

void process3(int n)
{
  for (int i = 0 ; i < n; i++) {
    // the first ancestor of every node i is parents[i]
    ancestors[i][0] = parents[i];
    for (int j = 1; 1 << j < n; j++)
      ancestors[i][j] = -1;
  }
  for (int j = 1; 1 << j < n; j++)
    for (int i = 0; i < n; i++)
      if (ancestors[i][j - 1] != -1)
        ancestors[i][j] = ancestors[ancestors[i][j - 1]][j - 1];
}

long long query(int p, int q)
{
  long long w = weights[p] + weights[q];
  //if p is situated on a higher level than q then we swap them
  if (levels[p] < levels[q])
    swap(p, q);
  // we compute the value of [log2(level[p)]
  int log;
  for (log = 1; 1 << log <= levels[p]; log++)
    ;
  log--;
  // we find the ancestor of node p situated on the same level
  // with q using the values in ancestors[][]
  for (int i = log; i >= 0; i--)
    if (levels[p] - (1 << i) >= levels[q])
      p = ancestors[p][i];
  if (p == q)
  return w - weights[p] * 2;
  // we compute LCA(p, q) using the values in ancestors[][]
  for (int i = log; i >= 0;i--)
    if (ancestors[p][i] != -1 && ancestors[p][i] != ancestors[q][i])
      p = ancestors[p][i], q = ancestors[q][i];
  return w - weights[parents[p]] * 2;
}

int main()
{
#ifdef __ELAPSED_TIME__
  clock_t start = clock();
#endif
  while (true) {
    int N;
    scanf("%d", &N);
    if (!N)
      break;
    for (int i = 0; i < N; i++)
      edges[i].clear();
    for (int v = 1; v < N; v++) {
      int u, w;
      scanf("%d %d", &u, &w);
      edges[u].push_back(edge(v, w)), edges[v].push_back(edge(u, w));
    }
    dfs(0, -1, 0);
    process3(N);
    int Q;
    scanf("%d", &Q);
    while (Q--) {
      int s, t;
      scanf("%d %d", &s, &t);
      printf("%lld%c", query(s, t), ((Q) ? ' ' : '\n'));
    }
  }
#ifdef __ELAPSED_TIME__
  fprintf(stderr, "elapsed time = %lf sec.\n",
    static_cast<double>(clock() - start) / CLOCKS_PER_SEC);
#endif
  return 0;
}

No comments:

Post a Comment