zoukankan      html  css  js  c++  java
  • BZOJ 1787 紧急集合(LCA)

    转换成抽象模型,就是要求一棵树(N个点,有N-1条边表示这个图是棵树)中某一点满足给定三点a,b,c到某一点的距离和最小。那么我们想到最近公共祖先的定义,推出只有集合点在LCA(a,b)、LCA(a,c)、LCA(b,c)中,才能保证距离和最近。

    # include <cstdio>
    # include <cstring>
    # include <cstdlib>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <set>
    # include <cmath>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi 3.1415926535
    # define eps 1e-9
    # define MOD 100000007
    # define INF 1000000000
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int i=a; i<=n; ++i)
    # define FO(i,a,n) for(int i=a; i<n; ++i)
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    # define mp make_pair
    # define pb push_back
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    int Scan() {
        int res=0, flag=0;
        char ch;
        if((ch=getchar())=='-') flag=1;
        else if(ch>='0'&&ch<='9') res=ch-'0';
        while((ch=getchar())>='0'&&ch<='9')  res=res*10+(ch-'0');
        return flag?-res:res;
    }
    void Out(int a) {
        if(a<0) {putchar('-'); a=-a;}
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    const int N=500005;
    //Code begin...
    
    struct Edge{int to, next;}edge[N<<1];
    int head[N], tot, fa[N][20], deg[N];
    queue<int>que;
    
    void add_edge(int u, int v){edge[tot].to=v; edge[tot].next=head[u]; head[u]=tot++;}
    void init(){tot=0; mem(head,-1);}
    void BFS(int root){
        deg[root]=0; fa[root][0]=root; que.push(root);
        while (!que.empty()) {
            int tmp=que.front(); que.pop();
            FO(i,1,20) fa[tmp][i]=fa[fa[tmp][i-1]][i-1];
            for (int i=head[tmp]; i!=-1; i=edge[i].next) {
                int v=edge[i].to;
                if (v==fa[tmp][0]) continue;
                deg[v]=deg[tmp]+1; fa[v][0]=tmp; que.push(v);
            }
        }
    }
    int LCA(int u, int v){
        if (deg[u]>deg[v]) swap(u,v);
        int hu=deg[u], hv=deg[v], tu=u, tv=v;
        for (int det=hv-hu, i=0; det; det>>=1, i++) if (det&1) tv=fa[tv][i];
        if (tu==tv) return tu;
        for (int i=19; i>=0; --i) {
            if (fa[tu][i]==fa[tv][i]) continue;
            tu=fa[tu][i]; tv=fa[tv][i];
        }
        return fa[tu][0];
    }
    int main ()
    {
        int n, m, u, v, w, x, y, tmp, p;
        init();
        n=Scan(); m=Scan();
        FO(i,1,n) scanf("%d%d",&u,&v), add_edge(u,v), add_edge(v,u);
        BFS(1);
        while (m--) {
            int ans=INF;
            scanf("%d%d%d",&u,&v,&w);
            x=LCA(u,v); tmp=deg[u]+deg[v]-2*deg[x];
            y=LCA(x,w); tmp+=(deg[x]+deg[w]-2*deg[y]);
            if (ans>tmp) p=x, ans=tmp;
            x=LCA(u,w); tmp=deg[u]+deg[w]-2*deg[x];
            y=LCA(x,v); tmp+=(deg[x]+deg[v]-2*deg[y]);
            if (ans>tmp) p=x, ans=tmp;
            x=LCA(v,w); tmp=deg[v]+deg[w]-2*deg[x];
            y=LCA(x,u); tmp+=(deg[x]+deg[u]-2*deg[y]);
            if (ans>tmp) p=x, ans=tmp;
            printf("%d %d
    ",p,ans);
        }
        return 0;
    }
    View Code

    复杂度O(n+m*logn).

  • 相关阅读:
    metasploit模块功能介绍
    虚拟机端口映射
    linux 双网卡实现
    斯坦福第三课:线性代数回顾(Linear Algebra Review)
    斯坦福第二课:单变量线性回归(Linear Regression with One Variable)
    斯坦福第一课:引言(Introduction)
    机器学习的个人见解----深夜总结
    史上最强机器学习资料------来自个人心血总结-----5星级
    如何学习新的知识----心血总结
    21个必知数据科学面试题和答案
  • 原文地址:https://www.cnblogs.com/lishiyao/p/6606081.html
Copyright © 2011-2022 走看看