1. 程式人生 > >[日常摸魚]luogu3398倉鼠找sugar-樹鏈剖分

[日常摸魚]luogu3398倉鼠找sugar-樹鏈剖分

lap efi 日常 tar include close 開始 amp add

https://www.luogu.org/problemnew/show/P3398

題意:一顆$n$個點的樹,$q$次詢問兩條鏈$(a,b),(c,d)$是否有交


樹剖裸題orz

一開始的想法是求出$lca_1=lca(a,b),lca_2=lca(c,d)$,對於深度大的那個$lca$用dfs序判斷是否在另一條鏈上,然後到現在都不知道為什麽一直wa…

改成判斷深度大的那個$lca$是否和另外兩個點的其中某個點有父子關系好像就行了…

技術分享圖片
#include<cstdio>
#include<cstring>
#include<algorithm>
using
namespace std; const int N=100005; inline int read() { int s=0,f=1;char c=getchar(); while(c<0||c>9){if(c==-)f=-1;c=getchar();} while(c>=0&&c<=9){s=s*10+c-0;c=getchar();} return s*f; } struct edge { int to,nxt; }edges[N<<1]; int n,q,tot,cnt; int head[N<<1
],size[N],son[N],dep[N],top[N],fa[N],tim[N]; inline void addEdge(int u,int v) { edges[++cnt]=(edge){v,head[u]}; head[u]=cnt; } #define cur edges[i].to inline void dfs1(int x) { size[x]=1; for(register int i=head[x];i;i=edges[i].nxt) if(cur!=fa[x]) { fa[cur]
=x;dep[cur]=dep[x]+1; dfs1(cur);size[x]+=size[cur]; if(size[son[x]]<size[cur])son[x]=cur; } } inline void dfs2(int x,int t) { top[x]=t;tim[x]=++tot; if(son[x])dfs2(son[x],t); for(register int i=head[x];i;i=edges[i].nxt) if(cur!=son[x]&&cur!=fa[x])dfs2(cur,cur); } #undef cur inline int lca(int a,int b) { while(top[a]!=top[b]) { if(dep[top[a]]<dep[top[b]])swap(a,b); a=fa[top[a]]; } if(dep[a]>dep[b])swap(a,b); return a; } int main() { n=read();q=read(); for(register int i=1;i<n;i++) { int u,v;u=read();v=read(); addEdge(u,v);addEdge(v,u); } dfs1(1);dfs2(1,1); for(register int i=1;i<=q;i++) { int a,b,c,d,lca1,lca2,res; a=read();b=read();c=read();d=read(); lca1=lca(a,b);lca2=lca(c,d); if(dep[lca1]<dep[lca2]) { swap(lca1,lca2); swap(a,c); swap(b,d); } if(lca(lca1,c)==lca1||lca(lca1,d)==lca1)res=1; else res=0; if(res)printf("Y\n"); else printf("N\n"); } return 0; }
View Code

如果有人知道一開始的方法為什麽錯了請務必告訴我orz

[日常摸魚]luogu3398倉鼠找sugar-樹鏈剖分