洛谷P3398 仓鼠找sugar(LCA+数学)

洛谷P3398 仓鼠找sugar(LCA+数学)_第1张图片洛谷P3398 仓鼠找sugar(LCA+数学)_第2张图片

可证明以下结论(虽然我每证出来):
在一棵树上:a-b最短路与c-d最短路有交集的充要条件为:a-b的距离+c-d的距离>=a-c的距离+b-d的距离。
然后分别求4个LCA就可以了。

#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn = 100010;
int tot;
int head[maxn], nxt[maxn * 2], ver[maxn * 2], wei[maxn * 2];
int dist[maxn];
int f[maxn][20];
int dep[maxn];

void addedge(int u, int v, int w)
{
	nxt[++tot] = head[u], head[u] = tot, ver[tot] = v; wei[tot] = w;
	nxt[++tot] = head[v], head[v] = tot, ver[tot] = u; wei[tot] = w;
}

int t; queue<int>q;
void bfs()
{
	q.push(1); dep[1] = 1;
	while (q.size())
	{
		int x = q.front(); q.pop();
		for (int i = head[x]; i != -1; i = nxt[i])
		{
			int y = ver[i];
			if (dep[y])continue;
			dep[y] = dep[x] + 1;
			dist[y] = dist[x] + wei[i];
			f[y][0] = x;
			for (int j = 1; j <= t; j++)
			{
				f[y][j] = f[f[y][j - 1]][j - 1];
			}
			q.push(y);
		}
	}
}

int lca(int x, int y)
{
	if (dep[x] > dep[y])swap(x, y);
	for (int i = t; i >= 0; i--)
	{
		if (dep[f[y][i]] >= dep[x])
			y = f[y][i];
	}
	if (x == y)return x;
	for (int i = t; i >= 0; i--)
	{
		if (f[x][i] != f[y][i])
		{
			x = f[x][i];
			y = f[y][i];
		}
	}
	return f[x][0];
}

int main()
{

	int n, m;
	scanf("%d%d", &n, &m);
	t = (int)(log(n) / log(2)) + 1;
	for (int i = 1; i <= n; i++)
	{
		head[i] = -1;
		dep[i] = 0;
	}
	tot = 0;
	for (int i = 1; i < n; i++)
	{
		int x, y, z;
		scanf("%d%d", &x, &y);
		addedge(x, y, 1);
	}
	bfs();
	for (int i = 1; i <= m; i++)
	{
		int x1, y1, x2, y2;
		scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
		int ans1 = dist[x1] + dist[y1] - 2 * dist[lca(x1, y1)] + dist[x2] + dist[y2] - 2 * dist[lca(x2, y2)];
		int ans2 = dist[x1] + dist[x2] - 2 * dist[lca(x1, x2)] + dist[y1] + dist[y2] - 2 * dist[lca(y1, y2)];
		if (ans1 >= ans2)
		{
			printf("Y\n");
		}
		else
		{
			printf("N\n");
		}
	}
}

洛谷P3398 仓鼠找sugar(LCA+数学)_第3张图片

你可能感兴趣的:(LCA)