Monday, September 1, 2014

Heavy Light Decomposition.

Solution for Live Archive 2045 - Closest Common Ancestors
/*
 * 11354.cpp
 *
 *  Created on: Sep 1, 2014
 *      Author: ghooo
 */

#include <cstring>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <algorithm>
#include <vector>
#include <set>
#include <complex>
#include <list>
#include <climits>
#include <cctype>
#include <bitset>
//#include <windows.h>

using namespace std;

#define pb push_back
#define all(v) v.begin(),v.end()
#define rall(v) v.rbegin(),v.rend()
#define sz(v) ((ll)v.size())
#define rep(i,m) for(int i=0;i<(int)(m);++i)
#define repe(i,n,m) for(int i=n;i<=(int)(m);++i)
#define rep2(i,n,m) for(int i=n;i<(int)(m);i++)
#define For(it,c) for(__typeof(c.begin()) it=c.begin();it!=c.end();++it)
#define reset(a,b) memset(a,b,sizeof(a))
#define mp make_pair
#define dot(a,b) ((conj(a)*(b)).X)
#define X real()
#define Y imag()
#define length(V) (hypot((V).X,(V).Y))
#define vect(a,b) ((b)-(a))
#define cross(a,b) ((conj(a)*(b)).imag())
#define normalize(v) ((v)/length(v))
#define rotate(p,about,theta) ((p-about)*exp(point(0,theta))+about)
#define pointEqu(a,b) (comp(a.X,b.X)==0 && comp(a.Y,b.Y)==0)
#define clrq(x) while(!x.empty()) x.pop();
#define clrvv(v) rep(i,sz(v))v[i].clear();
#define debug(x) cerr << #x << ": " << x << endl;
#define debugv(v) cerr << #v << ": ";For(it,v)cerr <<(*it)<<", "; cerr<<endl;

typedef stringstream ss;
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<pii> vpii;
typedef vector<string> vs;
typedef vector<int> vi;
typedef vector<double> vd;
typedef vector<vector<int> > vii;
typedef long double ld;
typedef complex<double> point;
typedef pair<point, point> segment;
typedef pair<double, point> circle;
typedef vector<point> polygon;
typedef unsigned long long ull;
typedef long long ll;

//==============================================================
// handling triples
typedef pair<ll,pair<ll,ll> > triple;
#define tfirst first
#define tsecond second.first
#define tthird second.second
#define mt(x,y,z) mp(x,mp(y,z))
//---------------------------------------------------------------

const int oo = (int) 1e9;
const double PI = 2 * acos(0.0);
const double eps = 1e-9;
const int MAXV = 50001, MAXE = 100001;
int head[MAXV], next[MAXE], to[MAXE], from[MAXE];
int parent[MAXV], siz[MAXV], lvl[MAXV], hvyChild[MAXV], hvyRoot[MAXV];
bool isHeavy[MAXE];
int last;
void init(){
 reset(head,-1);
 reset(parent,-1);
 last = 0;
}
void addEdge(int f, int t){
 isHeavy[last] = false;
 parent[t] = last;
 from[last] = f;
 to[last] = t;
 next[last] = head[f];
 head[f] = last++;
}
int dfs(int root, int depth){
 siz[root] = 1;
 lvl[root] = depth;
 hvyChild[root] = -1;
 hvyRoot[root] = root;
 for(int i = head[root]; i != -1; i = next[i])
  siz[root] += dfs(to[i], depth+1);
 for(int i = head[root]; i != -1; i = next[i])
  if(siz[to[i]] >= (siz[root]+1)/2){
   isHeavy[i] = true;
   hvyChild[root] = i;
  }
 return siz[root];
}
void heavyLight(int root = 0){
 dfs(root,0);
 for(int i = 0; i < last; i++){
  if(!isHeavy[i]) continue;
  int f = from[i];
  if(parent[f] == -1 || !isHeavy[parent[f]])
   for(int k = i; k != -1; k = hvyChild[to[k]])
    hvyRoot[to[k]] = f;
 }
}
int LCA(int a, int b){
 while(hvyRoot[a] != hvyRoot[b])
  if(lvl[hvyRoot[a]] > lvl[hvyRoot[b]])
   a = from[parent[hvyRoot[a]]];
  else
   b = from[parent[hvyRoot[b]]];
 if(lvl[a] < lvl[b])
  return a;
 return b;
}
int main(){
 ios_base::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
 freopen("in.txt", "r", stdin);
 //freopen("out.txt", "w", stdout);
#endif
 int n, m;
 while(~scanf("%d", &n)){
  init();
  int u, x, v;
  rep(i,n){
   scanf("%d:(%d)", &u, &x);
   --u;
   rep(k,x){
    scanf("%d", &v);
    --v;
    addEdge(u,v);
   }
  }
  int root = find(parent, parent+n, -1)-parent;
  heavyLight(root);
  scanf("%d", &m);
  vector<int> ans(n,0);
  rep(i,m){
   scanf(" (%d%d)", &u, &v);
   --u,--v;
   int lca = LCA(u,v);
   ans[lca]++;
  }
  rep(i,n){
   if(ans[i]) cout << i+1 << ":" << ans[i]<<endl;
  }
 }

 return 0;
}

No comments:

Post a Comment