[Luogu] 模板题-最近公共祖先
树链剖分版本:
1 #include<cstdio> 2 #include<iostream> 3 #define maxn 1000000 4 using namespace std; 5 6 int siz[maxn],fa[maxn],depth[maxn],son[maxn],top[maxn],n,m,s; 7 8 struct edge{ 9 int from,v; 10 }e[maxn]; 11 int tot,first[maxn]; 12 void insert(int u,int v){ 13 tot++; e[tot].from = first[u]; e[tot].v = v; first[u] = tot; 14 } 15 16 void dfs(int now){ 17 siz[now] = 1; 18 for(int i = first[now];i;i = e[i].from){ 19 int v = e[i].v; 20 if(v != fa[now]){ 21 fa[v] = now; 22 depth[v] = depth[now]+1; 23 dfs(v); 24 siz[now] += siz[v]; 25 if(!son[now] || siz[v] > siz[son[now]]) 26 son[now] = v; 27 } 28 } 29 } 30 31 void dfs2(int now,int t){ 32 top[now] = t; 33 if(!son[now]) return; 34 dfs2(son[now],t); 35 for(int i = first[now];i;i = e[i].from){ 36 int v = e[i].v; 37 if(v != fa[now] && v != son[now]) 38 dfs2(v,v); 39 } 40 } 41 42 int LCA(int u,int v){ 43 if(depth[top[u]] < depth[top[v]]) swap(u,v); 44 while(top[u] != top[v]){ 45 u = fa[top[u]]; 46 if(depth[top[u]] < depth[top[v]]) swap(u,v); 47 }if(depth[u] < depth[v]) swap(u,v); 48 return v; 49 } 50 51 int main(){ 52 scanf("%d%d%d",&n,&m,&s); 53 54 for(int i = 1;i < n;i++){ 55 int x,y; scanf("%d%d",&x,&y); 56 insert(x,y); insert(y,x); 57 }depth[s] = 1; dfs(s); dfs2(s,s); 58 59 while(m--){ 60 int u,v; 61 scanf("%d%d",&u,&v); 62 printf("%d\n",LCA(u,v)); 63 } 64 65 return 0; 66 }
Tarjan版本:
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #define maxn 500005 5 using namespace std; 6 7 struct edge{ 8 int from,u,v,ans,order; 9 }e[maxn*2+5],e1[maxn*2+5]; 10 11 int pre[maxn]; 12 int find(int x){ 13 if(!pre[x]) return x; 14 else{ 15 pre[x] = find(pre[x]); 16 return pre[x]; 17 } 18 } 19 20 bool book[maxn]; 21 int tot,tot1,first1[maxn],first[maxn],n,m,s; 22 void insert(int u,int v){ 23 tot++; 24 e[tot].from = first[u]; 25 e[tot].v = v; 26 e[tot].u = u; 27 first[u] = tot; 28 } 29 30 void insert1(int u,int v,int i){ 31 tot1++; 32 e1[tot1].order = i; 33 e1[tot1].from = first1[u]; 34 e1[tot1].u = u; 35 e1[tot1].v = v; 36 first1[u] = tot1; 37 } 38 39 bool cmp(const edge &a,const edge &b){ 40 return a.order < b.order; 41 } 42 43 void Tarjan(int now,int father){ 44 for(int i = first[now];i;i = e[i].from){ 45 int v = e[i].v; 46 if(v == father) continue; 47 Tarjan(v,now); 48 pre[find(v)] = find(now); 49 book[v] = true; 50 } 51 52 for(int i = first1[now];i;i = e1[i].from){ 53 int v = e1[i].v; 54 if(v == father) continue; 55 if(book[v]){ 56 e1[i].ans = find(v); 57 } 58 } 59 } 60 61 int main(){ 62 scanf("%d%d%d",&n,&m,&s); 63 for(int i = 1;i < n;i++){ 64 int a,b; 65 scanf("%d%d",&a,&b); 66 insert(a,b); 67 insert(b,a); 68 } 69 70 for(int i = 1;i <= m;i++){ 71 int a,b; 72 scanf("%d%d",&a,&b); 73 insert1(a,b,i); 74 insert1(b,a,i); 75 } 76 77 Tarjan(s,-1); 78 79 sort(e1+1,e1+1+tot1,cmp); 80 81 for(int i = 1;i <= tot1;i+=2){ 82 if(!e1[i].ans) printf("%d\n",e1[i+1].ans); 83 else printf("%d\n",e1[i].ans); 84 } 85 86 return 0; 87 }
转载请注明出处 -- 如有意见欢迎评论