luogu 3398 倉鼠找sugar
阿新 • • 發佈:2018-08-17
祖先 || wap swap 過多 iostream 數據 字母 餐廳
但是我們要判斷如何在兩天路徑上找相同的點。
經過多次畫圖發現,一條路徑上的$LCA$一定會出現在另一條路徑上。
所以我們就可以求$LCA$。
那麽我們需要判斷哪兩個條件呢?
設當前點$x$,判斷在$a$到$b$這條路徑上
題目描述
小倉鼠的和他的基(mei)友(zi)$sugar$住在地下洞穴中,每個節點的編號為$1~n$。地下洞穴是一個樹形結構。這一天小倉鼠打算從從他的臥室$(a)$到餐廳$(b)$,而他的基友同時要從他的臥室$(c)$到圖書館$(d)$。他們都會走最短路徑。現在小倉鼠希望知道,有沒有可能在某個地方,可以碰到他的基友?
小倉鼠那麽弱,還要天天被zzq大爺虐,請你快來救救他吧!
輸入輸出格式
輸入格式:
第一行兩個正整數$n$和$q$,表示這棵樹節點的個數和詢問的個數。
接下來$n-1$行,每行兩個正整數$u$和$v$,表示節點u到節點v之間有一條邊。
接下來$q$行,每行四個正整數$a$、$b$、$c$和$d$,表示節點編號,也就是一次詢問,其意義如上。
輸出格式:
對於每個詢問,如果有公共點,輸出大寫字母“Y”;否則輸出“N”。
輸入輸出樣例
輸入樣例#1:
5 5
2 5
4 2
1 3
1 4
5 1 5 1
2 2 1 4
4 1 3 4
3 1 1 5
3 5 1 4
輸出樣例#1:
Y
N
Y
Y
Y
說明
本題時限1s,內存限制128M,因新評測機速度較為接近NOIP評測機速度,請註意常數問題帶來的影響。
20%的數據$ n<=200,q<=200$
40%的數據 $n<=2000,q<=2000$
70%的數據 $n<=50000,q<=50000$
100%的數據 $n<=100000,q<=100000$
solution
這道題用裸的樹剖求$LCA$就可以做出來。
經過多次畫圖發現,一條路徑上的$LCA$一定會出現在另一條路徑上。
所以我們就可以求$LCA$。
那麽我們需要判斷哪兩個條件呢?
設當前點$x$,判斷在$a$到$b$這條路徑上
1.deep[x]>deep[LCA(a,b)]
2.LCA(x,a)==x||LCA(x,b}==x
這兩個條件的意思是
如果$x$比$LCA$要深,並且是兩個點任意一個點的祖先,那麽一定在這個簡單路徑上
code
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; const int N = 200000; int n,q; struct edge { int next,to; } e[N]; int head[N],tot,deep[N],fa[N],size[N],top[N],son[N],id[N],cnt,ind[N],root; void add(int x,int y) { e[++tot].next=head[x]; head[x]=tot; e[tot].to=y; } void dfs1(int x,int f) { fa[x]=f; size[x]=1; for(int i=head[x]; i; i=e[i].next) { int v=e[i].to; if(v!=f && !deep[v]) { deep[v]=deep[x]+1; dfs1(v,x); size[x]=size[v]+size[x]; if(size[v]>size[son[x]]) son[x]=v; } } } void dfs2(int x,int topf) { id[x]=++cnt; top[x]=topf; if(!son[x]) return; dfs2(son[x],topf); for(int i=head[x]; i; i=e[i].next) { int v=e[i].to; if(v!=fa[x] && !id[v]) dfs2(v,v); } } int LCA(int x,int y) { while(top[x]!=top[y]) { if(deep[top[x]]<deep[top[y]]) swap(x,y); x=fa[top[x]]; } return deep[x]<=deep[y]? x:y; } bool judge(int lca,int x,int y) { while(top[x]!=top[y]) { if(deep[top[x]]<deep[top[y]]) swap(x,y); x=fa[top[x]]; if(x==lca)return true; } return false; } int main() { cin >> n >> q; for(int i=1; i<=n-1; i++) { int a,b; cin >> a >> b; add(a,b); add(b,a); } root=1; deep[1]=1; dfs1(1,1); dfs2(1,1); while(q--) { int a,b,c,d; cin >> a >> b >> c >> d; int S=LCA(a,b); int T=LCA(c,d); if(S==T) { cout<<"Y"<<endl; continue; } if(deep[S]>=deep[LCA(S,T)])cout<<"Y"<<endl; else cout<<"N"<<endl; } }
luogu 3398 倉鼠找sugar