【洛谷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”。
输入输出样例
输入样例#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
题解:
转自:http://www.cnblogs.com/jsawz/p/6817094.html
一道提高+/省选-的题目,终于可以提高博客题目的平均难度了。。。
大致题意就是在一棵树上有两条路径,询问这两个路径是不是可以相交。
而如果两条路径相交的话,一定有一条路径a两端点的LCA在另一条的路径上,我们可以通过求路径a的LCA是不是在路径b上来求出a与b是不是相交的。
根据以上推断,可以保证了路径a的LCA的深度一定大于路径b的LCA的深度。只要再在确定路径a的LCA与路径b的两端点其中一点的LCA是路径a的LCA就确保路径a的LCA在路径b上了。
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const int maxn=100000+5; 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,q,m,num; int head[maxn],dep[maxn],f[maxn][18]; bool vis[maxn]; struct node { int next,to; }e[maxn*2]; 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]) { dep[to]=dep[x]+1; dfs(to,d+1); f[to][0]=x; } } } int Lca(int x,int y) { if(dep[x]<dep[y]) swap(x,y); for(int i=m;i>=0;i--) if(dep[x]-(1<<i)>=dep[y]) x=f[x][i]; if(x==y) return x; for(int i=m;i>=0;i--) if(f[x][i]&&f[x][i]!=f[y][i]) { x=f[x][i]; y=f[y][i]; } return f[x][0]; } int main() { n=read();q=read(); m=floor(log((double)n)/log(2.0)); 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<=m;j++) for(int i=1;i<=n;i++) f[i][j]=f[f[i][j-1]][j-1]; for(int i=1;i<=q;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\n");continue;} else {printf("N\n"); continue;} } if(dep[x]<dep[y]){ if(Lca(y,a)==y||Lca(y,b)==y) printf("Y\n"); else printf("N\n"); } if(dep[x]>dep[y]){ if(Lca(x,c)==x||Lca(x,d)==x) printf("Y\n"); else printf("N\n"); } } return 0; }
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define Me(Arr) memset(Arr,0,sizeof Arr); using namespace std; const int maxn=100005,maxe=200005; int n,Q; int lnk[maxn],nxt[maxe],son[maxe],tot; int size[maxn],fa[maxn],dep[maxn],gonxt[maxn],id[maxn],top[maxn],bottom[maxn],cloc; int bel[maxn],cnt; bool vis[maxn]; int read(){ int x=0; char ch=getchar(); while (ch<'0'||ch>'9') ch=getchar(); while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x; } void INIT(){ tot=cloc=cnt=0; Me(lnk); Me(nxt); Me(son); Me(size); Me(fa); Me(dep); Me(gonxt); Me(id); Me(top); Me(bottom); Me(bel); } void add(int x,int y){ nxt[++tot]=lnk[x],son[tot]=y,lnk[x]=tot; } void DFS_1(int x,int u,int layer){ size[x]=1,fa[x]=u,dep[x]=layer; for (int j=lnk[x]; j; j=nxt[j]) if (son[j]!=u){ DFS_1(son[j],x,layer+1); size[x]+=size[son[j]]; if (size[gonxt[x]]<size[son[j]]) gonxt[x]=son[j]; } } void DFS_2(int x){ id[x]=++cloc,bottom[x]=x; if (gonxt[x]){top[gonxt[x]]=top[x],bel[gonxt[x]]=bel[x]; DFS_2(gonxt[x]); bottom[x]=bottom[gonxt[x]];} for (int j=lnk[x]; j; j=nxt[j]) if (son[j]!=fa[x]&&son[j]!=gonxt[x]){ top[son[j]]=son[j],bel[son[j]]=++cnt; DFS_2(son[j]); } } void prepare(){ DFS_1(1,0,1); top[1]=bottom[1]=cnt=bel[1]=1; DFS_2(1); } int get(int x,int y){ if (bel[x]==bel[y]) return dep[x]<dep[y]?x:y; while (bel[x]!=bel[y]){ if (dep[top[x]]>dep[top[y]]) x=fa[top[x]]; else y=fa[top[y]]; } return dep[x]<dep[y]?x:y; } int main(){ n=read(),Q=read(),INIT(); for (int i=1; i<n; i++){ int x=read(),y=read(); add(x,y),add(y,x); } prepare(); for (; Q; Q--){ int a=read(),b=read(),c=read(),d=read(); int fx=get(a,b),fy=get(c,d); if (dep[fx]<dep[fy]) swap(a,c),swap(b,d),swap(fx,fy); if (fx==get(fx,c)||fx==get(fx,d)) puts("Y"); else puts("N"); } return 0; }
欢迎转载,转载请注明出处!