zoukankan      html  css  js  c++  java
  • codeforces 587C:(LCA倍增+维护最小值)

    一开始直接无脑tarjan,回溯只能一层层往上走,太慢了,加了各种优化还是TLE

    后来了解到LCA倍增法(在线)。复杂度其实相比LCA转RMQ以及tarjan是要稍差一些,但是其中能同步维护的只有LCA倍增,很神奇的算法

    #include"cstdio"
    #include"queue"
    #include"cmath"
    #include"stack"
    #include"iostream"
    #include"algorithm"
    #include"cstring"
    #include"queue"
    #include"map"
    #include"vector"
    #define ll long long
    
    using namespace std;
    const int MAXN = 1e5+50;
    const int MAXE = 200500;
    const int INF = 0x3f3f3f;
    
    struct node{
        int e,next;
        node(){}
        node(int a,int b):e(a),next(b){}
    }edge[MAXE];
    
    int n,m,q,tot;
    int vis[MAXN],first[MAXN],deep[MAXN];
    int p[MAXN][21];                    ///记录i往上跳2^j下到达的结点
    vector<int> G[MAXN][21],ans,num[MAXN];///G[i][j]记录i往上2^j个结点的10个最小值(不包括i结点,为的是更新方便)
    
    void init(){
        tot=0;
        memset(vis,0,sizeof(vis));
        memset(first,-1,sizeof(first));
        memset(p,-1,sizeof(p));
    }
    
    void addedge(int u,int v){
        edge[tot]=node(v,first[u]);
        first[u]=tot++;
        edge[tot]=node(u,first[v]);
        first[v]=tot++;
    }
    
    void update(vector<int> a,vector<int> b,vector<int> &c){    ///合并
        int sa=a.size();
        int sb=b.size();
        int i=0,j=0;
        int va,vb;
        while(i+j<10&&(i<sa||j<sb)){
            if(i<sa) va=a[i];
            else va=INF;
            if(j<sb) vb=b[j];
            else vb=INF;
            if(va<vb){
                c.push_back(va);
                i++;
            }
            else{
                c.push_back(vb);
                j++;
            }
        }
    }
    
    void Merge(vector<int> &a,vector<int> b){   ///合并
        int sb=b.size();
        for(int i=0;i<sb;i++) a.push_back(b[i]);
    }
    
    void init_p(){
        for(int j=1;(1<<j)<=n;j++)
        for(int i=1;i<=n;i++) if(p[i][j-1]!=-1) {
            p[i][j]=p[p[i][j-1]][j-1];                  ///i往上跳2^j相当于i往上跳2次2^(j-1)
            update(G[i][j-1],G[p[i][j-1]][j-1],G[i][j]);
        }
    }
    
    void dfs(int u,int dep){
        vis[u]=1;
        deep[u]=dep;
        for(int i=first[u];i!=-1;i=edge[i].next){
            int v=edge[i].e;
            if(vis[v]) continue;
            p[v][0]=u;          ///初始化,2^0=1,相当于父亲节点
            G[v][0]=num[u];     ///初始化
            dfs(v,dep+1);
        }
    }
    
    void get_lca(int u,int v,int k){
        if(deep[u]<deep[v]) swap(u,v);  ///保证deep[u]>deep[v]便于操作
    
        int a=u,b=v;        ///先不合并u,v内的元素,以免重复,故先保存下来
        ans.clear();
    
        int dif=deep[u]-deep[v];
        for(int i=0;i<=20;i++) if(dif&(1<<i)){
            Merge(ans,G[u][i]);
            u=p[u][i];
        }
        if(u!=v){
            for(int i=20;i>=0;i--) if(p[u][i]!=-1&&p[u][i]!=p[v][i]){
                Merge(ans,G[v][i]);
                Merge(ans,G[u][i]);
                v=p[v][i];
                u=p[u][i];
            }
            Merge(ans,num[a]);          ///这种情况是u,v分属lca的两个子树
            Merge(ans,num[b]);
            Merge(ans,num[p[u][0]]);
        }
        else Merge(ans,num[a]);         ///这种情况下v就是LCA,故只合并u
        sort(ans.begin(),ans.end());
        int t=min(k,(int)ans.size());
        cout<<t<<' ';
        for(int i=0;i<t;i++) cout<<ans[i]<<' ';
        cout<<endl;
    }
    
    int main(){
        //freopen("in.txt","r",stdin);
        scanf("%d%d%d",&n,&m,&q);
        init();
    
        for(int i=1;i<n;i++){
            int u,v;scanf("%d%d",&u,&v);
            addedge(u,v);
        }
        for(int i=1;i<=m;i++){
            int t;scanf("%d",&t);
            if(num[t].size()<10) num[t].push_back(i);
        }
        dfs(1,1);
        init_p();
        for(int i=0;i<q;i++){
            int u,v,k;
            scanf("%d%d%d",&u,&v,&k);
            get_lca(u,v,k);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    关于 OpenSmtp 邮件标题过长后出现乱码问题的解决
    用于解析 sohu 新闻页面的 XSLT 文件
    CEGUI 0.7x实现下划线描边图文混排等效果
    Hash算法说明
    D3DXMatrixShadow 函数
    DLL动态链接库和LIB静态链接库之程序员经验分析
    printf格式控制符的完整格式(转载)
    深入说明HDR技术
    Irrlicht不定期分析
    8.3实例程序:平面阴影
  • 原文地址:https://www.cnblogs.com/luxiaoming/p/5094016.html
Copyright © 2011-2022 走看看