主要是注意输入,我用的是RMQ算法求LCA,在询问特多时比tarjan的时间要少。
#include<iostream> #include<vector> #include<cmath> #include<algorithm> using namespace std; const int N=1008; int vis[N],val[N],p[N]; int first[N*2],node[N*2],dep[N*2],dp[N*2][25]; int mi[25];//移位运算 vector<int>map[N];//邻接表 int lc[N],in[N]; void dfs(int &index,int u,int d) { index++;//时间搓,全部遍历一次并记录所有节点的父亲,为查找公共祖先做准备 node[index]=u; dep[index]=d; vis[u]=1; first[u]=index; for(int i=0;i<map[u].size();i++) { if(!vis[map[u][i]]) { dfs(index,map[u][i],d+1); index++; node[index]=u; dep[index]=d; } } } void rmq_init(int n)//RMQ预处理 { int i; int K = (int)(log((double)n) / log(2.0)); for(i=1; i<=n; i++) dp[i][0] = i; for(int j=1; j<=K; j++) for(i=1; i+mi[j]-1 <= n ; i++) { int a = dp[i][j-1]; int b = dp[i+mi[j-1]][j-1]; if(dep[a] < dep[b]) dp[i][j] = a; else dp[i][j] = b; } } int rmq(int x,int y) { int k=(int)(log((double)(y-x+1))/log(2.0)); int a=dp[x][k]; int b=dp[y-mi[k]+1][k]; if(dep[a]<dep[b])//最近公共祖先的深度 return a; else return b; } int lca(int a,int b) { int x=first[a]; int y=first[b]; int k; if(x>y)//可用swap,但是我以前用了超时,所以再也不敢用了。 { k=rmq(y,x); return node[k]; } else { k=rmq(x,y); return node[k]; } } int main() { int i,j,n,m,a,b; for(i=0;i<20;i++) mi[i]=1<<i; while(scanf("%d",&n)!=EOF) { memset(in,0,sizeof(in)); for(i=0;i<=n;i++) map[i].clear(); for(i=0;i<n;i++) { scanf("%d:(%d)",&a,&m); for(j=0;j<m;j++) { scanf("%d",&b); map[a].push_back(b); map[b].push_back(a); in[b]++; } } memset(vis,0,sizeof(vis)); int tot=0; for(i=1;i<=n;i++) if(!in[i]) dfs(tot,i,1); rmq_init(tot); scanf("%d",&m); getchar(); memset(lc,0,sizeof(lc)); for(i=0;i<m;i++) { scanf(" (%d %d)",&a,&b); lc[lca(a,b)]++; } for(i=1;i<=n;i++) { if(lc[i]) printf("%d:%d ",i,lc[i]); } } return 0; } /** */