很简单的题目,给出一棵树,最多有N(N<=10000)个节点,然后给出N-1个父子关系,然后是M次查询(M<=100000),问A是否是B的祖先。
很明显的搜索题,但是千万别傻乎乎的对每一次询问都搜一次。。。不TLE就怪了。我们可以对这棵树进行一遍DFS,在DFS的过程中记录下每个节点开始访问的深度first和结束访问的深度second。那么对于两个节点A和B,A是B的祖先当且仅当first[A] < first[B] < second[A];
这样以来,对于每一个查询就是O(1)的复杂度了。
PS:建图的时候我分别用了两种方法,一个用vector一个自己写的链表。还是贴自己写的链表吧,在时间卡的紧的题上vector会TLE的。
#include <cstdio> #include <cstring> #include <vector> #define MAXN 10005 using namespace std; int first[MAXN],second[MAXN],head[MAXN]; int n,depth,size; bool flag[MAXN]; struct Edge{ int v,next; Edge(){} Edge(int _v,int _next):v(_v),next(_next){} }edge[MAXN]; inline void initial(){ size = 0; memset(head,-1,sizeof(head)); } inline void add_edge(int u,int v){ edge[size] = Edge(v,head[u]); head[u] = size++; } inline void DFS(int t){ int i; flag[t] = true; first[t] = depth++; for(i = head[t];i != -1; i = edge[i].next){ int u = edge[i].v; if(!flag[u]) DFS(u); } second[t] = depth++; } int main() { int i,j,k,T,u,v,Q; scanf("%d",&T); while(T--){ scanf("%d",&n); memset(first,0,sizeof(first)); memset(second,0,sizeof(second)); memset(flag,false,sizeof(flag)); initial(); for(i = 1;i < n; ++i){ scanf("%d%d",&u,&v); add_edge(v,u); } depth = 0; DFS(0); scanf("%d",&Q); while(Q--){ scanf("%d%d",&u,&v); if(first[u] < first[v] && second[u] > first[v]) printf("Yes/n"); else printf("No/n"); } printf("/n"); } }