洛谷P3398 倉鼠找sugar
阿新 • • 發佈:2017-05-06
網上 etc 最短路徑 pan pac space nbsp -m 不能
題目描述
小倉鼠的和他的基(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
【思路】
放一個倍增法求lca的板子,然後求四邊lca。
題目是一個點從A出發到B 一個從C出發到D 那麽從A到B可以分解成 先從A到X 再從X到B。。。 C同理 假設能相遇 那麽 要麽在A到X的過程A,B相遇 要麽在X到B的過程A,B相遇 對於在A到X的過程相遇的情況 又可以分解為: 情況1: 在A到X的過程和 C到Y的過程 中A,B相遇 情況2: 在A到X的過程和 Y到D的過程 中A,B相遇 另一種情況同理。。。
以上是粘的洛谷上的 昨天在徐老大的幫助下成功理解為什麽(就是下面代碼的方法)
在X Y中取一個最大,再在lca(a,c).lca(a,d),lca(b,c),lca(b,d)這四個當中取一個最大,如果後者的深度大於等於前者,那麽可以相遇,否則不能;
我們從頭來說一下吧;
相遇的情況 a->X,c->y 相遇(可以認為 松鼠和他基友都在網上沖)
a->X,y->d 相遇(一個往上沖,一個在往下沖)
X->b,c->Y 相遇(一個往下沖 一個往上沖)
X->b,Y->d 相遇(都往下沖)
根據樹中的每一個節點的父親都是唯一的,lca可以認為是他們最短路徑上深度最淺的那個點,a,b,c,d到他們lca的路徑是唯一的。
而上述的4個lca中深度最大的那一個 我們姑且記為S,那麽S一定是a,b中的一個(有a無b,有b無a,我們假設是①)和c,d的一個(有c無d 有d無c,我們假設是②)的lca(仔細理解哦)
那麽如果s的深度大於x,y中較大的的那一個,說明①在和②在往上沖的過程中一定要經過他們的lca,也就是S,再經過x或者是y。因為①和②是 a,b中的一個和c,d中的一個,他們還要沖向x或者是y呢。這種情況必然相遇;
還有徐老大給我講的她看的題解。
(1)第一種特別明顯的不會有路徑相交的情況是,最深的那個lca比淺的lca的那兩個點還深,就一定不會用路徑交集。
(2)有路徑交集的情況在淺的lca的路徑一定覆蓋深的lca的路徑,那麽深的lca這個點的一定在淺的Lca的子樹裏,那麽
假如淺的Lca和深的lca的那兩個點的lca是淺的的這個點本身,那麽路徑一定有交集。。。。。。
【題解】
1 #include<iostream> 2 #include<cstdio> 3 #include<vector> 4 using namespace std; 5 #define N 100009 6 vector<int>vec[N]; 7 int n,q,u,v,a,b,c,d; 8 int dad[N][22],depth[N]; 9 int read() 10 { 11 int x=0,f=1; 12 char ch=getchar(); 13 while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} 14 while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}//是&& 15 return f*x; 16 } 17 void dfs(int x) 18 { 19 depth[x]=depth[dad[x][0]]+1; 20 for(int i=0;dad[x][i];i++)//先進行這一步 21 { 22 dad[x][i+1]=dad[dad[x][i]][i]; 23 } 24 for(int i=0;i<vec[x].size();i++) 25 { 26 if(!depth[vec[x][i]]) 27 { 28 dad[vec[x][i]][0]=x; 29 dfs(vec[x][i]); 30 } 31 } 32 } 33 int lca(int x,int y) 34 { 35 if(depth[x]>depth[y]) 36 swap(x,y); 37 for(int i=20;i>=0;i--) 38 { 39 if(depth[dad[y][i]]>=depth[x])//到相同的深度 40 { 41 y=dad[y][i]; 42 } 43 } 44 if(x==y)return x; 45 for(int i=20;i>=0;i--) 46 { 47 if(depth[dad[x][i]]!=depth[dad[y][i]]) 48 x=dad[x][i],y=dad[y][i]; 49 } 50 return dad[x][0]; 51 } 52 int main() 53 { 54 n=read();q=read(); 55 for(int i=1;i<=n-1;i++) 56 { 57 u=read();v=read(); 58 vec[u].push_back(v); 59 vec[v].push_back(u); 60 } 61 dfs(1); 62 for(int i=1;i<=q;i++) 63 { 64 a=read();b=read();c=read();d=read(); 65 int tep=max(depth[lca(a,b)],depth[lca(c,d)]); 66 int res=max(max(depth[lca(a,c)],depth[lca(a,d)]), 67 max(depth[lca(b,c)],depth[lca(b,d)])); 68 if(res>=tep) 69 printf("Y\n"); 70 else 71 printf("N\n"); 72 } 73 return 0; 74 }
洛谷P3398 倉鼠找sugar