题目连接: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; }