题目连接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=141
思路:LCA->RMQ + DFS + ST(在线算法)
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
using namespace std;
#define max 1000
int n,m;
int v1,v2,vt;
char c;
int * adj[max];//邻接表
int num[max];//记录邻接表每一行的节点数
int root[max];//是否是根节点的标志
int color[max];//dfs颜色,0:white,1:gray,2:black
int E[max<<1];//深度优先搜索 欧拉环游
int L[max<<1];//节点的深度
int H[max];//节点第一次出现的位置
int total;//节点出现顺序
int M[max<<1][12];//ST数组
int outp[max];//最后输出
void dfs(int s,int d)
{
color[s] = 1;
E[++total] = s;
L[total] = d;
H[s] = total;
for(int i=1; i<=num[s]; i++)
{
if(color[adj[s][i]] == 0)
{
dfs(adj[s][i],d+1);
}
E[++total] = s;
L[total] = d;
}
color[s] = 2;
}
int rmq(int u,int v)
{
int k;
k = (int)(log(v-u+1)/log(2));
return L[M[u][k]] < L[M[v-(1<<k)+1][k]] ? M[u][k] : M[v-(1<<k)+1][k];
}
int lca(int u,int v)
{
if(H[u]<H[v])
{
return E[rmq(H[u],H[v])];
}
else
{
return E[rmq(H[v],H[u])];
}
}
void process()
{
int ln = (n<<1) - 1;
for(int i=1; i<=ln; i++)
{
M[i][0] = i;
}
for(int j=1; (1<<j)<=ln; j++)
{
for(int i=1; i+(1<<j)-1<=ln; i++)
{
if(L[M[i][j-1]] < L[M[i+(1<<(j-1))][j-1]])
{
M[i][j] = M[i][j-1];
}
else
{
M[i][j] = M[i+(1<<(j-1))][j-1];
}
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int u,v;
while(scanf("%d",&n)!=EOF)
{
memset(root,0,sizeof(root));
memset(color,0,sizeof(color));
memset(num,0,sizeof(num));
memset(outp,0,sizeof(outp));
total = 0;
for(int i=1; i<=n; i++)
{
scanf("%d ",&v1);
scanf("%c",&c);
while(c!=':')
{
scanf("%c",&c);
}
scanf("%c",&c);
while(c!='(')
{
scanf("%c",&c);
}
scanf("%d",&vt);
scanf("%c",&c);
while(c!=')')
{
scanf("%c",&c);
}
if(vt!=0)
{
adj[v1] = new int[vt + 1];
num[v1] = vt;
for(int j = 1; j<=vt; j++)
{
scanf("%d",&v2);
adj[v1][j] = v2;
root[v2] = 1;
//printf("adj[%d][%d] = %d\n",v1,j,adj[v1][j]);
}
}
}
int index;
for(index = 1; index<=sizeof(root); index++)
{
if(root[index]!=1)
{
break;
}
}
dfs(index,1);
process();
scanf("%d",&m);
for(int i=1; i<=m; i++)
{
scanf("%c",&c);
while(c!='(')
{
scanf("%c",&c);
}
scanf("%d",&u);
scanf("%c",&c);
while(c!=',')
{
scanf("%c",&c);
}
scanf("%d",&v);
outp[lca(u,v)]++;
scanf("%c",&c);
while(c!=')')
{
scanf("%c",&c);
}
}
for(int i=1; i<=n; i++)
{
if(outp[i]!=0)
{
printf("%d:%d\n",i,outp[i]);
}
}
}
return 0;
}