zoukankan      html  css  js  c++  java
  • Query on a tree II 倍增LCA

    You are given a tree (an undirected acyclic connected graph) with N nodes, and edges numbered 1, 2, 3...N-1. Each edge has an integer value assigned to it, representing its length.

    We will ask you to perfrom some instructions of the following form:

    • DIST a b : ask for the distance between node a and node b
      or
    • KTH a b k : ask for the k-th node on the path from node a to node b

    Example:
    N = 6
    1 2 1 // edge connects node 1 and node 2 has cost 1
    2 4 1
    2 5 2
    1 3 1
    3 6 2

    Path from node 4 to node 6 is 4 -> 2 -> 1 -> 3 -> 6
    DIST 4 6 : answer is 5 (1 + 1 + 1 + 2 = 5)
    KTH 4 6 4 : answer is 3 (the 4-th node on the path from node 4 to node 6 is 3)

    Input

    The first line of input contains an integer t, the number of test cases (t <= 25). t test cases follow.

    For each test case:

    • In the first line there is an integer N (N <= 10000)
    • In the next N-1 lines, the i-th line describes the i-th edge: a line with three integers a b c denotes an edge between a, b of cost c (c <= 100000)
    • The next lines contain instructions "DIST a b" or "KTH a b k"
    • The end of each test case is signified by the string "DONE".

    There is one blank line between successive tests.

    Output

    For each "DIST" or "KTH" operation, write one integer representing its result.

    Print one blank line after each test.

    Example

    Input:
    1
    
    6
    1 2 1
    2 4 1
    2 5 2
    1 3 1
    3 6 2
    DIST 4 6
    KTH 4 6 4
    DONE
    
    Output:
    5
    3
    
    看到树上两点距离很容易想到LCA,
    对于第K个点我们同样可以倍增解决;
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<map>
    #include<set>
    #include<vector>
    #include<queue>
    #include<bitset>
    #include<ctime>
    #include<time.h>
    #include<deque>
    #include<stack>
    #include<functional>
    #include<sstream>
    //#include<cctype>
    //#pragma GCC optimize(2)
    using namespace std;
    #define maxn 200005
    #define inf 0x7fffffff
    //#define INF 1e18
    #define rdint(x) scanf("%d",&x)
    #define rdllt(x) scanf("%lld",&x)
    #define rdult(x) scanf("%lu",&x)
    #define rdlf(x) scanf("%lf",&x)
    #define rdstr(x) scanf("%s",x)
    #define mclr(x,a) memset((x),a,sizeof(x))
    typedef long long  ll;
    typedef unsigned long long ull;
    typedef unsigned int U;
    #define ms(x) memset((x),0,sizeof(x))
    const long long int mod = 9999973;
    #define Mod 1000000000
    #define sq(x) (x)*(x)
    #define eps 1e-5
    typedef pair<int, int> pii;
    #define pi acos(-1.0)
    //const int N = 1005;
    #define REP(i,n) for(int i=0;i<(n);i++)
    typedef pair<int, int> pii;
    
    inline int rd() {
    	int x = 0;
    	char c = getchar();
    	bool f = false;
    	while (!isdigit(c)) {
    		if (c == '-') f = true;
    		c = getchar();
    	}
    	while (isdigit(c)) {
    		x = (x << 1) + (x << 3) + (c ^ 48);
    		c = getchar();
    	}
    	return f ? -x : x;
    }
    
    
    ll gcd(ll a, ll b) {
    	return b == 0 ? a : gcd(b, a%b);
    }
    int sqr(int x) { return x * x; }
    
    
    
    /*ll ans;
    ll exgcd(ll a, ll b, ll &x, ll &y) {
    	if (!b) {
    		x = 1; y = 0; return a;
    	}
    	ans = exgcd(b, a%b, x, y);
    	ll t = x; x = y; y = t - a / b * y;
    	return ans;
    }
    */
    
    struct node {
    	int u, v, w, nxt;
    }e[maxn];
    int head[maxn];
    int tot;
    int n;
    int dis[maxn], dep[maxn];
    int fa[maxn][20];
    void init() {
    	ms(e); ms(head); tot = 0; ms(dis); ms(dep);
    	ms(fa);
    }
    
    void addedge(int u, int v, int w) {
    	e[++tot].u = u; e[tot].v = v; e[tot].nxt = head[u]; e[tot].w = w;
    	head[u] = tot;
    }
    
    
    void dfs(int rt) {
    	for (int i = 1; i <= (int)log(n) / log(2) + 1; i++)
    		fa[rt][i] = fa[fa[rt][i - 1]][i - 1];
    	for (int i = head[rt]; i; i = e[i].nxt) {
    		int v = e[i].v;
    		if (v == fa[rt][0])continue;
    		fa[v][0] = rt; dep[v] = dep[rt] + 1;
    		dis[v] = dis[rt] + e[i].w;
    		dfs(v);
    	}
    }
    
    int LCA(int x, int y) {
    	if (dep[x] > dep[y])swap(x, y);
    	for (int i = (int)log(n) / log(2) + 1; i >= 0; i--) {
    		if (dep[fa[y][i]] >= dep[x])y = fa[y][i];
    	}
    	if (x == y)return x;
    	for (int i = (int)log(n) / log(2) + 1; i >= 0; i--) {
    		if (fa[x][i] != fa[y][i]) {
    			x = fa[x][i]; y = fa[y][i];
    		}
    	}
    	return fa[x][0];
    }
    
    int main()
    {
    //	ios::sync_with_stdio(0);
    	int T = rd();
    	while (T--) {
    		n = rd();
    		init();
    		for (int i = 1; i < n; i++) {
    			int u = rd(), v = rd(), w = rd();
    			addedge(u, v, w); addedge(v, u, w);
    		}
    		dfs(1);
    		char op[20];
    		while (rdstr(op) != EOF && op[1] != 'O') {
    			if (op[1] == 'I') {
    				int u = rd(), v = rd();
    			//	cout << dis[u] << ' ' << dis[v] << ' ' << dis[LCA(u, v)] << endl;
    				printf("%d
    ", dis[u] + dis[v] - 2 * dis[LCA(u, v)]);
    			}
    			else {
    				int u = rd(), v = rd(), k = rd();
    				int root = LCA(u, v);
    				int ans;
    				if (dep[u] - dep[root] + 1 >= k) {
    					ans = dep[u] - k + 1;
    					int i;
    					for (i = 0; (1 << i) <= dep[u]; i++); i--;
    					for (int j = i; j >= 0; j--) {
    						if (dep[u] - (1 << j) >= ans)u = fa[u][j];
    					}
    					printf("%d
    ", u);
    				}
    				else {
    					ans = dep[root] + k - (dep[u] - dep[root] + 1);
    					int i;
    					for (i = 0; (1 << i) <= dep[v]; i++); i--;
    					for (int j = i; j >= 0; j--) {
    						if (dep[v] - (1 << j) >= ans)v = fa[v][j];
    					}
    					printf("%d
    ", v);
    				}
    			}
    		}
    	}
    	return 0;
    }
    
    EPFL - Fighting
  • 相关阅读:
    梯度下降法
    超平面
    感知机模型
    三角不等式
    统计学习方法基本概念
    Kaggle 的注册和使用
    win10 部署 Anaconda
    全概率和贝叶斯公式
    行列式
    伴随矩阵
  • 原文地址:https://www.cnblogs.com/zxyqzy/p/10355532.html
Copyright © 2011-2022 走看看