XOR回廊 (KUPC 2012)

http://kupc2012.contest.atcoder.jp/tasks/kupc2012_11#

問題

解法

解説参照

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <math.h>
#include <assert.h>
#include <vector>
#include <queue>
#include <string>
#include <map>
#include <set>

using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define FORIT(it, c) for (__typeof((c).begin())it = (c).begin(); it != (c).end(); it++)
#define MEMSET(v, h) memset((v), h, sizeof(v))

struct Edge {
  int src;
  int dest;
  ll cost;
  Edge() {;}
  Edge(int src, int dest, ll cost) : src(src), dest(dest), cost(cost) {;}
};

typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

int n, m, q;
Graph g;
int visit[100010];
ll dist[100010];
ll base[100];

void Push(ll v) {
  int first = -1;
  for (int i = 60; i >= 0; i--) {
    if (v & (1LL << i)) {
      v ^= base[i];
      if (v & (1LL << i)) { first = max(first, i); }
    }
  }
  assert(first != -1 || v == 0);
  if (first != -1) { base[first] = v; }
}

void dfs(int from, int parent, ll cost) {
  if (visit[from] == 2) { return; }
  if (visit[from] == 1) {
    Push(cost ^ dist[from]);
    return;
  }
  visit[from] = 1;
  dist[from] = cost;
  FORIT(it, g[from]) {
    int to = it->dest;
    if (to == parent) { continue; }
    dfs(to, from, cost ^ it->cost);
  }
  visit[from] = 2;
}

int main() {
  while (scanf("%d %d %d", &n, &m, &q) > 0) {
    MEMSET(visit, 0);
    MEMSET(dist, -1);
    MEMSET(base, 0);
    g = Graph(n);
    REP(i, m) {
      int f, t;
      ll w;
      int v = scanf("%d %d %lld", &f, &t, &w);
      assert(v == 3);
      g[f].push_back(Edge(f, t, w));
      g[t].push_back(Edge(t, f, w));
    }
    dfs(0, 0, 0);
    REP(iter, q) {
      int f, t;
      int v = scanf("%d %d", &f, &t);
      assert(v == 2);
      ll ans = dist[f] ^ dist[t];
      for (int i = 60; i >= 0; i--) {
        if (!(ans & (1LL << i))) { ans ^= base[i]; }
      }
      printf("%lld\n", ans);
    }
  }
}