《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,q≤200。

40% 的数据 n,q≤2×103。

70% 的数据 n,q≤5×104。

100% 的数据 1≤n,q≤105。

代码实现:

#include<bits/stdc++.h>

using namespace std;

const int MAX_NODE = 100010;

int fMAX_NODE25, depthMAX_NODE, distanceMAX_NODE;

int logLevel, totalNodes, totalQueries, edgeCount;

int adjVer2\*MAX_NODE, adjNext2\*MAX_NODE, adjHeadMAX_NODE;

queue<int> bfsQueue;

void addEdge(int fromNode, int toNode) {

adjVer++edgeCount = toNode;

adjNextedgeCount = adjHeadfromNode;

adjHeadfromNode = edgeCount;

}

int findLCA(int nodeA, int nodeB) {

if (depthnodeA > depthnodeB) {

swap(nodeA, nodeB);

}

for (int k = logLevel; k >= 0; k--) {

if (depthf\[nodeBk] >= depthnodeA) {

nodeB = fnodeBk;

}

}

if (nodeA == nodeB) {

return nodeA;

}

for (int k = logLevel; k >= 0; k--) {

if (fnodeAk != fnodeBk) {

nodeA = fnodeAk;

nodeB = fnodeBk;

}

}

return fnodeA0;

}

int getDistance(int nodeX, int nodeY) {

int lcaNode = findLCA(nodeX, nodeY);

return distancenodeX + distancenodeY - 2 * distancelcaNode;

}

int main() {

scanf("%d%d", &totalNodes, &totalQueries);

logLevel = (int)(log(totalNodes) / log(2)) + 1;

for (int i = 1; i <= totalNodes; i++) {

adjHeadi = 0;

depthi = 0;

}

for (int i = 1; i < totalNodes; i++) {

int from, to;

scanf("%d%d", &from, &to);

addEdge(from, to);

addEdge(to, from);

}

bfsQueue.push(1);

depth1 = 1;

distance1 = 0;

while (!bfsQueue.empty()) {

int currentNode = bfsQueue.front();

bfsQueue.pop();

for (int i = adjHeadcurrentNode; i; i = adjNexti) {

int neighborNode = adjVeri;

if (depthneighborNode) {

continue;

}

depthneighborNode = depthcurrentNode + 1;

distanceneighborNode = distancecurrentNode + 1;

fneighborNode0 = currentNode;

for (int k = 1; k <= logLevel; k++) {

fneighborNodek = ff\[neighborNodek-1]k-1;

}

bfsQueue.push(neighborNode);

}

}

for (int i = 1; i <= totalQueries; i++) {

int path1Start, path1End, path2Start, path2End;

scanf("%d%d%d%d", &path1Start, &path1End, &path2Start, &path2End);

int distPath1 = getDistance(path1Start, path1End);

int distPath2 = getDistance(path2Start, path2End);

int crossDist1 = getDistance(path1Start, path2Start);

int crossDist2 = getDistance(path1End, path2End);

if (distPath1 + distPath2 >= crossDist1 + crossDist2) {

printf("Y\n");

} else {

printf("N\n");

}

}

return 0;

}