zoukankan      html  css  js  c++  java
  • NC13950 Alliances(LCA)

    对于每个帮派求他们的lca,对于每个询问,先将所含的所有帮派求lca,将这个和当前首都比较,如果首都不在最高点的lca的子树当中,那么他的答案就是这个最高点lca和首都的距离

    如果在这个子树下,那么只需要求取dfs序在首都前后的两个点求一个min即可。

    分析这道题目,我们想到lca的原因是,这里有树上两点的距离的判定,这种题,很多情况下都是lca来做,但是因为题目中有很多点,因此我们要缩减计算的次数。通过思考,我们发现对于可以分成两种情况讨论。而对于子树中的情况,其实不难想到dfs序+二分查找,因为前后总是最近的,其他的点没有意义。有个点是因为两个城市之间的所有城市都是特殊点,因此,求得前后点后,还要进一步转化。这个转化比较明显,可以通过观察获得。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=1e6+10;
    const int mod=1e9+7;
    int h[N],ne[N],e[N],idx;
    int dfn[N],times;
    int f[N][35];
    int depth[N];
    vector<int> num[N];
    int p[N];
    int id[N];
    int sz[N];
    void add(int a,int b){
        e[idx]=b,ne[idx]=h[a],h[a]=idx++;
    }
    void dfs(int u,int fa){
        depth[u]=depth[fa]+1;
        f[u][0]=fa;
        dfn[u]=++times;
        id[times]=u;
        int i;
        for(i=1;i<=30;i++){
            f[u][i]=f[f[u][i-1]][i-1];
        }
        for(i=h[u];i!=-1;i=ne[i]){
            int j=e[i];
            if(j==fa)
                continue;
            dfs(j,u);
        }
    }
    int lca(int a,int b){
        if(depth[a]<depth[b])
            swap(a,b);
        int i;
        for(i=30;i>=0;i--){
            if(depth[f[a][i]]>=depth[b]){
                a=f[a][i];
            }
        }
        if(a==b)
            return a;
        for(i=30;i>=0;i--){
            if(f[a][i]!=f[b][i]){
                a=f[a][i];
                b=f[b][i];
            }
        }
        return f[a][0];
    }
    int cal(int a,int b){
        return depth[a]+depth[b]-2*depth[lca(a,b)];
    }
    int main(){
        ios::sync_with_stdio(false);
        int n;
        cin>>n;
        int i;
        memset(h,-1,sizeof h);
        for(i=1;i<n;i++){
            int a,b;
            cin>>a>>b;
            add(a,b);
            add(b,a);
        }
        dfs(1,0);
        int k;
        cin>>k;
        for(i=1;i<=k;i++){
            int x;
            cin>>x;
            int now;
            for(int j=1;j<=x;j++){
                int y;
                cin>>y;
                num[i].push_back(dfn[y]);
                if(j==1){
                    now=y;
                }
                else{
                    now=lca(now,y);
                }
            }
            p[i]=now;
            sort(num[i].begin(),num[i].end());
        }
        int q;
        cin>>q;
        while(q--){
            int v,c;
            cin>>v>>c;
            int now;
            for(i=1;i<=c;i++){
                cin>>sz[i];
                if(i==1){
                    now=p[sz[i]];
                }
                else{
                    now=lca(now,p[sz[i]]);
                }
            }
            if(lca(now,v)!=now){
                cout<<-2*depth[lca(now,v)]+depth[v]+depth[now]<<endl;
                continue;
            }
            int ans=0x3f3f3f3f;
            for(i=1;i<=c;i++){
                int pos=lower_bound(num[sz[i]].begin(),num[sz[i]].end(),dfn[v])-num[sz[i]].begin();
                if(pos!=(int)num[sz[i]].size()){
                    int tmp=lca(v,id[num[sz[i]][pos]]);
                    ans=min(ans,cal(tmp,v));
                }
                pos=lower_bound(num[sz[i]].begin(),num[sz[i]].end(),dfn[v])-num[sz[i]].begin()-1;
                if(pos!=-1){
                    int tmp=lca(v,id[num[sz[i]][pos]]);
                    ans=min(ans,cal(tmp,v));
                }
            }
            cout<<ans<<endl;
        }
    }
    View Code
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    三次请求(读-改-读)引出nibernate 一级缓存
    算法竞赛入门经典第一、二章摘记
    uva 10905 Children's Game
    uva 11205 The broken pedometer
    uva 10160 Servicing stations
    uva 208 Firetruck
    uva 167 The Sultan's Successors
    zoj 1016 Parencodings
    uva 307 Sticks
    uva 216 Getting in Line
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/13966484.html
Copyright © 2011-2022 走看看