列表

详情


NC252834. Chasing Game

描述

Colin and Eva are playing a chasing game on a given tree with n nodes, indexed from 1 to n.

Colin knows that Eva will start from node S at time 0 , and move towards her destination node T at the speed of 1 edge per second. (i.e. Assuming that the path from S to T is p_0, p_1, \cdots, p_k,\text{ } p_0 = S, p_k = T , then Eva will arrive at node p_i at time i ) After arriving at node T, Eva will stay still there until she is caught by Colin.

Now Colin wants to chase Eva. At time 0, Colin is at node S' ; every second Colin can choose to stay still at the current node or to move once along the edge connected to the current node, and arrive at the other node of this edge at the end of this second.

Colin wants to chase Eva as soon as possible. Can you tell him what's the minimum time that Colin and Eva will be at the same node.

Colin and Eva will play this game q times, you need to tell Colin the minimum time for every game, and the corresponding index of the node.

输入描述

The first line contains two integers n, q \text{ } ( 1 \le n,q \le 2 \times 10^5) , representing the number of nodes and the times Eva and Colin play the chasing game for.

For the following n - 1 lines, each line contains two integers u_i, v_i \text{ } ( 1 \le u_i, v_i \le n, u_i \neq v_i) , representing that there is an edge connecting node u_i and node
v_i . It's guaranteed that the given edges form a tree.

For the following q lines, each line contains three integers S_i,T_i,S'_i \text{ } (1 \le S_i, T_i, S'_i \le n,S_i \neq T_i ) , representing the start point for Eva, the end point for Eva, and the start point for Colin.

输出描述

Output q lines.

The i-th line contains two integers t_i,p_i , representing the minimum time that Colin and Eva will be at the same node is t_i , and the index of this node is p_i .

It can be proved there is only one possible value of p_i for each game.

示例1

输入:

5 3
1 2
1 3
3 4
3 5
4 1 2
3 5 1
5 2 4

输出:

2 1
2 5
1 3

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 582ms, 内存消耗: 40468K, 提交时间: 2023-06-06 11:29:43

#include<bits/stdc++.h>
using namespace std;
const int N = 200010;
const int M = 400010;
int n, m;
int head[N], pre[M], ver[M], tot;
void add(int x,int y){
    ver[++tot]=y; pre[tot]=head[x]; head[x]=tot;
}
int fa[N][22], dep[N];
void dfs(int x,int f){
    for (int i=1;i<=20;++i) fa[x][i]=fa[fa[x][i-1]][i-1];
    for (int i=head[x]; i; i=pre[i]){
        int v=ver[i];
        if (v==f) continue;
        fa[v][0]=x; dep[v]=dep[x]+1;
        dfs(v,x);
    }
}
int lca(int x,int y){
    if (dep[x]<dep[y]) swap(x,y);
    for (int i=20;i>=0;--i){
        if (dep[fa[x][i]]>=dep[y]) x=fa[x][i];
    }
    if (x==y) return x;
    for (int i=20;i>=0;--i){
        if (fa[x][i]!=fa[y][i]) x=fa[x][i], y=fa[y][i];
    }
    return fa[x][0];
}
int getdis(int x,int y){return dep[x]+dep[y]-2*dep[lca(x,y)];}
int getfa(int x,int k){
    for (int i=20;i>=0;--i){
        if (k>>i&1) x=fa[x][i];
    }
    return x;
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n>>m;
    for (int i=1;i<n;++i){
        int x,y; cin>>x>>y;
        add(x,y); add(y,x);
    }
    dep[1]=1; dfs(1,0);
    while(m--){
        int x,y,z; cin>>x>>y>>z;
        int t=(getdis(x,z)+1)/2, p;
        int l=lca(x,z);
        if (dep[x]-dep[l]>=t) p=getfa(x,t);
        else p=getfa(z,getdis(x,z)-t);
//        printf("p=%d t=%d\n",p,t);
        int anst, ansp;
        if (getdis(x,p)+getdis(y,p)==getdis(x,y)){
            anst=max(getdis(x,p),getdis(z,p));
            ansp=p;
        }
        else anst=getdis(z,y), ansp=y;
        printf("%d %d\n",anst,ansp);
    }
    return 0;
}

C++(clang++ 11.0.1) 解法, 执行用时: 794ms, 内存消耗: 41248K, 提交时间: 2023-07-06 21:18:06

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int f[N][22], d[N];
vector<int> g[N];

void dfs(int u, int fa) {
	d[u] = d[fa] + 1;
	for (int i = 1; i <= 20; i++) {
		f[u][i] = f[f[u][i - 1]][i - 1];
	}
	for (auto v : g[u]) {
		if (v == fa) continue;
		f[v][0] = u;
		dfs(v, u);
	}
}

int lca(int a, int b) {
	if (d[a] < d[b]) swap(a, b);
	for (int i = 20; i >= 0; i--) {
		if (d[f[a][i]] >= d[b]) a = f[a][i];
	}
	if (a == b) return a;
	for (int i = 20; i >= 0; i--) {
		if (f[a][i] != f[b][i]) {
			a = f[a][i];
			b = f[b][i];
		}
	}
	return f[a][0];
}

int dis(int a, int b) {
	return d[a] + d[b] - 2 * d[lca(a, b)];
}

int jump(int x, int distance) {
	for (int i = 0; i <= 20; i++) {
		if (distance >> i & 1) {
			x = f[x][i];
		}
	}
	return x;
}

int get(int a, int b, int distance) {
	int LCA = lca(a, b);
	int len = dis(a, b);
	if (d[a] - d[LCA] >= distance) {
		return jump(a, distance);
	} else {
		return jump(b, len - distance);
	}
}

int main() {

	cin.tie(nullptr)->ios::sync_with_stdio(false);
	int n, q;
	cin >> n >> q;
	for (int i = 1; i < n; i++) {
		int u, v;
		cin >> u >> v;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	dfs(1, 0);
	while (q--) {
		int a, b, c;
		cin >> a >> b >> c;
		int dac = dis(a, c), dbc = dis(b, c), dab = dis(a, b);
		if (dab < dbc) {
            cout << max(dab, dbc) << ' ' << b << '\n';
        } else {
            cout << (dac + 1) / 2 << ' ' << get(a, c, (dac + 1) / 2) << '\n';
        }
	}


	return 0;
}

上一题