求调,sub0#12和sub1#0越界,还有几个点超时
查看原帖
求调,sub0#12和sub1#0越界,还有几个点超时
768692
InoriILU楼主2023/5/24 17:43

qwq

#include <iostream>

typedef int EdgeType;
typedef int DataType;

const int MAXN{500000 + 10};
const int MAXLog{19 + 5};
int Log2[MAXN]{}, father[MAXN][MAXLog]{}, deep[MAXN]{}; //father 存储 i 点的 2 ^ k 级祖先
bool visit[MAXN];

struct Edge
{
	EdgeType end; //终点
	EdgeType next; //以 i 为起点,第一条边的存储位置,倒序
};
EdgeType head[MAXN]{};
EdgeType count{1};
Edge storage[MAXN];

void addedge(EdgeType start, EdgeType end);
void dfs(EdgeType now, EdgeType father = 0); //求出每个点的深度
int lca(int a, int b);

int main()
{
	using namespace std;
	cin.tie(0);
	cout.tie(0);
	ios_base::sync_with_stdio(false);
	//memset(head, -1, sizeof(head));

	int n{}, m{}, s{};
	cin >> n >> m >> s;
	for (int i = 2; i <= n; i++)
	{
		Log2[i] = Log2[i / 2] + 1;
	}

	for (int i{}, x{}, y{}; i < n - 1; i++)
	{
		cin >> x >> y;
		addedge(x, y);
		addedge(y, x); //无向图!
	}
	dfs(s);
	for (int i{}, a{}, b{}; i < m; i++)
	{
		cin >> a >> b;
		cout << lca(a, b) << "\n";
	}
}

void addedge(EdgeType start, EdgeType end)
{
	storage[count].end = end;
	storage[count].next = head[start];
	head[start] = count++;
};

void dfs(EdgeType now, EdgeType father)
{
	if (visit[now]) return;
	visit[now] = true;
	deep[now] = deep[father] + 1; //子 = 父 + 1
	::father[now][0] = father;

	for (int i = 1; i <= Log2[deep[now]]; i++) //范围小于深度的 log2
	{
		using ::father;
		father[now][i] = father[father[now][i - 1]][i - 1]; //跳一半再跳一半
	}

	for (int edge = head[now]; edge; edge = storage[edge].next)
	{
		if(storage[edge].end != father)
			dfs(storage[edge].end, now);
	}
};

int lca(int a, int b) 
{
	if (deep[a] > deep[b]) //设 a 的深度 <= b
	{
		std::swap(a, b);
	}
	while (deep[a] != deep[b]) //直到深度相等为止
	{
		b = father[b][Log2[deep[b] - deep[a]]]; //b 向上跳
	}
	if (a == b)
	{
		return a;
	}
	for (int i = Log2[deep[a]]; i >= 0; i--) //从可能跳的最大步数开始
	{
		if (father[a][i] != father[b][i])
		{
			a = father[a][i], b = father[b][i]; //在 a, b 不相遇的情况下跳得尽量高
		}
	}
	return father[a][0];
};

2023/5/24 17:43
加载中...