• bzoj 1787: [Ahoi2008]Meet 紧急集合【树链剖分lca】


    对于三个点求最小路径长度和,答案肯定在某两个点的lca上,因为如果把集合点定在公共lca上,一定有两个点汇合后再一起上到lca,这样显然不如让剩下的那个点下来
    这个lca可能是深度最深的……但是我懒得证了,反正只有三个lca,每个都求一遍然后取个max就好啦

    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int N=500005;
    int n,m,h[N],cnt,de[N],si[N],fa[N],hs[N],fr[N];
    struct qwe
    {
    	int ne,to;
    }e[N<<1];
    int read()
    {
    	int r=0,f=1;
    	char p=getchar();
    	while(p>'9'||p<'0')
    	{
    		if(p=='-')
    			f=-1;
    		p=getchar();
    	}
    	while(p>='0'&&p<='9')
    	{
    		r=r*10+p-48;
    		p=getchar();
    	}
    	return r*f;
    }
    void add(int u,int v)
    {
    	cnt++;
    	e[cnt].ne=h[u];
    	e[cnt].to=v;
    	h[u]=cnt;
    }
    void dfs1(int u,int fat)
    {
        fa[u]=fat;
        de[u]=de[fat]+1;
        si[u]=1;
        for(int i=h[u];i;i=e[i].ne)
            if(e[i].to!=fat)
            {
                dfs1(e[i].to,u);
                si[u]+=si[e[i].to];
                if(si[e[i].to]>si[hs[u]])
                    hs[u]=e[i].to;
            }
    }
    void dfs2(int u,int top)
    {
        fr[u]=top;
        if(!hs[u])
            return;
        dfs2(hs[u],top);
        for(int i=h[u];i;i=e[i].ne)
            if(e[i].to!=fa[u]&&e[i].to!=hs[u])
                dfs2(e[i].to,e[i].to);
    }
    int lca(int u,int v)
    {//cerr<<u<<"    "<<v<<endl;
        for(;fr[u]!=fr[v];de[fr[u]]>de[fr[v]]?u=fa[fr[u]]:v=fa[fr[v]]);
        return de[u]<de[v]?u:v;
    }
    int main()
    {
    	n=read(),m=read();
    	for(int i=1;i<n;i++)
    	{
    		int x=read(),y=read();
    		add(x,y),add(y,x);
    	}
    	dfs1(1,0);
    	dfs2(1,1);
    	while(m--)
    	{
    		int x=read(),y=read(),z=read(),lc1=lca(x,y),lc2=lca(y,z),lc3=lca(z,x),lc,ans=1e9,p,nw;//cerr<<x<<" "<<y<<" "<<z<<endl;
    		lc=lca(lc1,z);//cerr<<lc<<endl;
    		nw=de[x]-de[lc1]+de[y]-de[lc1]+de[z]-de[lc]+de[lc1]-de[lc];
    		if(nw<ans)
    			ans=nw,p=lc1;
    		lc=lca(lc2,x);//cerr<<lc<<endl;
    		nw=de[y]-de[lc2]+de[z]-de[lc2]+de[x]-de[lc]+de[lc2]-de[lc];
    		if(nw<ans)
    			ans=nw,p=lc2;
    		lc=lca(lc3,y);//cerr<<lc<<endl;
    		nw=de[z]-de[lc3]+de[x]-de[lc3]+de[y]-de[lc]+de[lc3]-de[lc];
    		if(nw<ans)
    			ans=nw,p=lc3;
    		printf("%d %d
    ",p,ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    Jenkins 的安装部署
    Python /usr/bin/python
    java学习基础 项目
    Java 并行与并发
    c# 将一个窗体显示在主窗体中
    java.io.IOException: open failed: EACCES (Permission denied) 问题解决
    android中创建模拟器的 SDCard
    Android学习笔记__2__Android工程目录结构
    Android学习笔记__3__Android应用程序组成
    Android学习笔记__1__Android体系架构
  • 原文地址:https://www.cnblogs.com/lokiii/p/9646235.html
Copyright © 2020-2023  润新知