[蓝桥杯][2018年第九届真题]版本分支(离线LCA模板)
题目描述 小明负责维护公司一个奇怪的项目。这个项目的代码一直在不断分支(branch)但是从未发生过合并(merge)。 现在这个项目的代码一共有N个版本,编号1~N,其中1号版本是最初的版本。 除了1号版本之外,其他版本的代码都恰好有一个直接的父版本;即这N个版本形成了一棵以1为根的树形结构。
如下图就是一个可能的版本树:
1
/ 2 3 | / 5 4 6
现在小明需要经常检查版本x是不是版本y的祖先版本。你能帮助小明吗?
输入 第一行包含两个整数N和Q,代表版本总数和查询总数。 以下N-1行,每行包含2个整数u和v,代表版本u是版本v的直接父版本。 再之后Q行,每行包含2个整数x和y,代表询问版本x是不是版本y的祖先版本。 输出 对于每个询问,输出YES或NO代表x是否是y的祖先。
样例输入 6 5 1 2 1 3 2 5 3 6 3 4 1 1 1 4 2 6 5 2 6 4 样例输出 YES YES NO NO NO 这个题是真的狗,时间卡的很严。在线LCA算法TLE了。单纯的离线LCA也会TLE,但是比在线的过的样例多。我是用的离线LCA+快读,然后才过的。题目本身不难,就是一个LCA,算是模板了。 代码如下:
#include<bits/stdc++.h> #define ll long long #define Pll pair<int,int> using namespace std; const int MAXN = 1e5+100; struct node{ int y,id; node (int a,int b) { y=a,id=b; } }; vector<node> vec[MAXN]; bool vis[MAXN]; int per[MAXN],head[MAXN],in_num[MAXN],ans[MAXN],a[MAXN]; map<Pll,int> mp; int cnt,n,m; struct Node { int c,next; }edge[MAXN]; inline int read() { char ch = getchar(); int x = 0, f = 1; while(ch < 0 || ch > 9) { if(ch == -) f = -1; ch = getchar(); } while(0 <= ch && ch <= 9) { x = x * 10 + ch - 0; ch = getchar(); } return x * f; } void Init() { cnt = 0; memset(in_num,0,sizeof(in_num)); memset(head,-1,sizeof(head)); memset(vis,0,sizeof(vis)); for(int i =1;i <= n;i++) { vec[i].clear(); per[i] = i; } } void add(int x,int y) { edge[++cnt].next = head[x]; edge[cnt].c = y; head[x] = cnt; } int Find(int x) { if(per[x] != x) per[x] = Find(per[x]); return per[x]; } void Union(int x,int y) { x = Find(x);y = Find(y); if(x == y) return ; per[x] = y; } void Tarjan(int x) { for(int i = head[x];i != -1; i =edge[i].next) { int v = edge[i].c; Tarjan(v); Union(v,x); } vis[x] = 1; for(int i = 0;i < vec[x].size();i ++) if(vis[vec[x][i].y]) ans[vec[x][i].id]=Find(vec[x][i].y); } int main() { int x,y; n=read(),m=read(); Init(); for(int i = 1;i < n;i++) { x=read(),y=read(); add(x,y); in_num[y] ++; } for(int i = 0;i < m;i ++) { x=read(),y=read(); vec[x].push_back(node(y,i)); vec[y].push_back(node(x,i)); a[i]=x; } int root; root=1; Tarjan(root); for(int i=0;i<m;i++) { if(a[i]!=ans[i]) printf("NO "); else printf("YES "); } return 0; }
努力加油a啊,(o)/~