• BZOJ1787 [Ahoi2008]Meet 紧急集合 【LCA】


    1787: [Ahoi2008]Meet 紧急集合

    Time Limit: 20 Sec  Memory Limit: 162 MB
    Submit: 3578  Solved: 1635
    [Submit][Status][Discuss]

    Description

    Input

    Output

    Sample Input

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

    Sample Output


    5 2
    2 5
    4 1
    6 0

    HINT



    点很少,只有三个,画一下图,手动模拟一下就会发现:我们要求的就是画一条线将三个点连起来,使线最短

    由于树路径的唯一性,连接三个点的路径是唯一的,但是由于走法的不同会导致因为重复部分路径而使路径增长


    未使路径最短,我们就不能走复路,所以我们只需求出三者最大的LCA,再将另外一个点走上LCA所在路径就好了

    如图:


    具体LCA用倍增实现,复杂度O(mlogn + nlogn),一个是预处理,一个是询问

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define LL long long int
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define Redge(u) for (int k = head[u]; k != -1; k = edge[k].next)
    using namespace std;
    const int maxn = 500005,maxm = 1000005,INF = 1000000000;
    inline int RD(){
    	int out = 0,flag = 1; char c = getchar();
    	while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
    	while (c >= 48 && c <= 57) {out = (out << 1) + (out << 3) + c - '0'; c = getchar();}
    	return out * flag;
    }
    int dep[maxn],fa[maxn][20];
    int N,M,head[maxn],nedge = 0,p[4];
    struct node{int lca,u,v;}e[4];
    struct EDGE{int to,next;}edge[maxm];
    inline void build(int u,int v){
    	edge[nedge] = (EDGE){v,head[u]}; head[u] = nedge++;
    	edge[nedge] = (EDGE){u,head[v]}; head[v] = nedge++;
    }
    void dfs(int u,int f,int d){
    	dep[u] = ++d; fa[u][0] = f;
    	Redge(u) if (edge[k].to != f) dfs(edge[k].to,u,d);
    }
    void init(){REP(j,19) REP(i,N) fa[i][j] = fa[fa[i][j - 1]][j - 1];}
    int LCA(int u,int v){
    	if (dep[u] < dep[v]) u ^= v ^= u ^= v;
    	int d = dep[u] - dep[v];
    	for (int i = 0; (1 << i) <= d; i++)
    		if ((1 << i) & d) u = fa[u][i];
    	if (u == v) return u;
    	for (int i = 19; i >= 0; i--)
    		if (fa[u][i] != fa[v][i]) u = fa[u][i],v = fa[v][i];
    	return fa[u][0];
    }
    void B_Sort(){
    	for (int i = 1; i <= 3; i++)
    		for (int j = i + 1; j <= 3; j++)
    			if (dep[e[i].lca] > dep[e[j].lca]) swap(e[i],e[j]);
    }
    void solve(){
    	int ans,u;
    	while (M--){
    		REP(i,3) p[i] = RD();
    		for (int i = 1,k = 0; i < 3; i++)
    			for (int j = i + 1; j <= 3; j++)
    				e[++k].u = i,e[k].v = j,e[k].lca = LCA(p[i],p[j]);
    		B_Sort();
    		//REP(i,3) printf("%d and %d  lca: %d
    ",e[i].u,e[i].v,e[i].lca);
    		REP(i,3) if (i != e[1].u && i != e[1].v) {u = p[i];break;}
    		ans = dep[p[e[1].u]] + dep[p[e[1].v]] + dep[u] - 2 * dep[e[1].lca] - dep[e[3].lca];
    		printf("%d %d
    ",e[3].lca,ans);
    	}
    }
    int main(){
    	memset(head,-1,sizeof(head));
    	N = RD(); M = RD();
    	REP(i,N - 1) build(RD(),RD());
    	dfs(1,0,0); init();
    	solve();
    	return 0;
    }
    



  • 相关阅读:
    200. Number of Islands(DFS)
    DoubleDQN---tensorflow实现
    133. Clone Graph(图的复制)
    python deque
    136. Single Number(位运算)
    C++中位运算
    anacoda 安装默认源中没有的包
    kali系统安装图文教程
    C#基础|初探反射
    一般处理程序(ashx)和页面处理程序(aspx)的区别
  • 原文地址:https://www.cnblogs.com/Mychael/p/8282777.html
Copyright © 2020-2023  润新知