洛谷P3398 仓鼠找sugar
题目描述
小仓鼠的和他的基(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”。
输入输出样例
说明
__本题时限1s,内存限制128M,因新评测机速度较为接近NOIP评测机速度,请注意常数问题带来的影响。__
20%的数据 n<=200,q<=200
40%的数据 n<=2000,q<=2000
70%的数据 n<=50000,q<=50000
100%的数据 n<=100000,q<=100000
代码
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=100000+5; inline int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-')f=-1; ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} return x*f; } int n,m,num; int head[maxn],f[maxn][20],dep[maxn]; bool vis[maxn]; struct node { int next,to; }e[maxn<<1]; void add(int from,int to) { e[++num].next=head[from]; e[num].to=to; head[from]=num; } void dfs(int x,int d) { vis[x]=1;dep[x]=d; for(int i=head[x];i;i=e[i].next) { int to=e[i].to; if(!vis[to]) { f[to][0]=x; dfs(to,d+1); } } } int lca(int a,int b) { if(dep[a]<dep[b]){int t=a;a=b;b=t;} int d=dep[a]-dep[b]; for(int i=0;i<=18;i++) if(d&(1<<i)) a=f[a][i]; if(a==b) return a; for(int i=18;i>=0;i--) if(f[a][i]!=f[b][i]) { a=f[a][i]; b=f[b][i]; } return f[a][0]; } int main() { n=read();m=read(); for(int i=1;i<n;i++) { int x,y; x=read();y=read(); add(x,y);add(y,x); } dfs(1,1); for(int j=1;j<=18;j++) for(int i=1;i<=n;i++) f[i][j]=f[f[i][j-1]][j-1]; for(int i=1;i<=m;i++) { int a,b,c,d,x,y; a=read();b=read(); c=read();d=read(); x=lca(a,b);y=lca(c,d); if(dep[x]==dep[y]) { if(x==y) printf("Y "); else printf("N "); } else if(dep[x]>dep[y]) { if(dep[c]<dep[x]&&dep[d]<dep[x]) {printf("N ");continue;} if(lca(x,c)==x||lca(x,d)==x) {printf("Y ");continue;} printf("N "); } else if(dep[x]<dep[y]) { if(dep[a]<dep[y]&&dep[b]<dep[y]) {printf("N ");continue;} if(lca(y,a)==y||lca(y,b)==y) {printf("Y ");continue;} printf("N "); } } return 0; }