P4248 [AHOI2013]差異(字尾陣列+單調棧)
阿新 • • 發佈:2020-09-11
https://www.luogu.com.cn/problem/P3379
\(Tarjan\)求\(LCA\)
\(dfs\)訪問每個節點,當一個節點被訪問結束後,直接將該節點並在它的父親上,然後處理詢問
用\(vector\)儲存一端在\(u\)的詢問,倘若\(v\)已經被訪問到了,那麼把\(v\)所並的集合的祖先取出就是該詢問的答案。因為一個集合為一個子樹,\(v\)已經被訪問到了,那麼這個集合就是包含\(u,v\)的最小子樹根節點,當然是\(lca\)了
\(Code:\)
#include<iostream> #include<cstdio> #include<algorithm> #include<vector> #define N 500005 using namespace std; int n,m,rt,x,y,tot,f[N],fr[N],nxt[N << 1],d[N << 1]; int rf[N],ans[N]; struct node { int x,y; node (int xx=0,int yy=0) { x=xx,y=yy; } }; vector<node>e[N]; void add(int x,int y) { tot++; d[tot]=y; nxt[tot]=fr[x]; fr[x]=tot; } int getf(int x) { return (x==rf[x])?x:(rf[x]=getf(rf[x])); } void dfs(int u) { rf[u]=u; for (int i=fr[u];i;i=nxt[i]) { int v=d[i]; if (v==f[u]) continue; f[v]=u; dfs(v); rf[v]=u; } for (vector<node> :: iterator it=e[u].begin();it!=e[u].end();++it) if (rf[it->x]) ans[it->y]=getf(it->x); } int main() { scanf("%d%d%d",&n,&m,&rt); for (int i=1;i<n;i++) { scanf("%d%d",&x,&y); add(x,y),add(y,x); } for (int i=1;i<=m;i++) scanf("%d%d",&x,&y),e[x].push_back(node(y,i)),e[y].push_back(node(x,i)); dfs(rt); for (int i=1;i<=m;i++) printf("%d\n",ans[i]); return 0; }