【问题描述】
已知一棵n个节点的有根树。有m个询问。每个询问给出了一对节点的编号x和y,询问x与y的祖孙关系。
【输入格式】
输入第一行包括一个整数n表示节点个数。
接下来n行每行一对整数对a和b表示a和b之间有连边。如果b是-1,那么a就是树的根。
第n+2行是一个整数m表示询问个数。
接下来m行,每行两个正整数x和y。
【输出格式】
对于每一个询问,输出1:如果x是y的祖先,输出2:如果y是x的祖先,否则输出0。
【样例输入】
10
234 -1
12 234
13 234
14 234
15 234
16 234
17 234
18 234
19 234
233 19
5
234 233
233 12
233 13
233 15
233 19
【样例输出】
1
0
0
0
2
【数据规模】
对于30%的数据,n,m≤1000。
对于100%的.据,n,m≤40000,每个节点的编号都不超过40000。
这是去年我们考的一套题,现在回过头来看,其实不难啊,谁知道当年还做的要死要活的
这题就是一个裸的LCA,毕竟题目都这样说了
我用了tarjan,因为个人来说我的tarjan打的要差一些,但是打了这题后,我对tarjan求LCA的理解要正常的许多了
裸的tarjan,额外处理就是储存一个对每一个询问边的最近公共祖先,但是我们建立询问边是建立了两条,所以要注意在储存答案时要合并起来
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #define maxn 40005
9 using namespace std;
10
11 struct node{
12 int u,v,nxt;
13 }e[maxn*4],p[maxn*4];
14
15 int n,m,dfn[maxn],fa[maxn],belong[maxn],root,maxid;
16 int head[maxn],heap[maxn],vis[maxn*4],visid[maxn];
17 int ord[maxn*4];
18
19 int tot;
20 void adde(int u,int v){e[tot]=(node){u,v,head[u]};head[u]=tot++;}
21
22 int tpt;
23 void addp(int u,int v,int pos){p[tpt]=(node){u,v,heap[u]};
24 ord[tpt]=pos;heap[u]=tpt++;
25 }
26
27 int find(int x){if(fa[x]==x)return x;return fa[x]=find(fa[x]);}
28
29 int num;
30 void tarjan(int u,int from){
31 dfn[u]=++num;
32 for(int i=head[u];i!=-1;i=e[i].nxt ){
33 int v=e[i].v;
34 if(!dfn[v]){tarjan(v,u);fa[v]=u;visid[v]=1;}
35 }
36 for(int i=heap[u];i!=-1;i=p[i].nxt){
37 int vv=p[i].v;
38 if(visid[vv]&&!vis[ord[i]]){vis[ord[i]]=find(vv);}
39 }
40 }
41
42 int main(){
43 freopen("tarjanlca.txt","r",stdin);
44 memset(head,-1,sizeof(head));
45 memset(heap,-1,sizeof(heap));
46 scanf("%d",&n);
47 for(int i=1;i<=n;i++){
48 int u,v;scanf("%d%d",&u,&v);
49 if(v==-1){root=u;continue;}
50 adde(u,v);adde(v,u);maxid=max(maxid,max(u,v));
51 }
52 for(int i=1;i<=maxid;i++)fa[i]=i;
53 scanf("%d",&m);
54 for(int i=1;i<=m;i++){
55 int u,v;scanf("%d%d",&u,&v);
56 addp(u,v,i);addp(v,u,i);
57 }visid[root]=1;
58 tarjan(root,0);
59 for(int i=1;i<=m;i++){
60 int lca=vis[i],pos=(i-1)*2;
61 if(lca==p[pos].u ) puts("1");
62 else if(lca==p[pos].v )puts("2");
63 else puts("0");
64 }
65 }
【总结】
tarjan大法好,可惜皮不来啊