• poj1470 LCA+RMQ


    主要是注意输入,我用的是RMQ算法求LCA,在询问特多时比tarjan的时间要少。

    #include<iostream>
    #include<vector>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const int N=1008;
    int vis[N],val[N],p[N];
    int first[N*2],node[N*2],dep[N*2],dp[N*2][25];
    int mi[25];//移位运算
    vector<int>map[N];//邻接表
    int lc[N],in[N];
    void dfs(int &index,int u,int d)
    {
        index++;//时间搓,全部遍历一次并记录所有节点的父亲,为查找公共祖先做准备
        node[index]=u;
        dep[index]=d;
        vis[u]=1;
        first[u]=index;
        for(int i=0;i<map[u].size();i++)
        {
            if(!vis[map[u][i]])
            {
                dfs(index,map[u][i],d+1);
                index++;
                node[index]=u;
                dep[index]=d;
            }
        }
    }
    void rmq_init(int n)//RMQ预处理
    {
        int i;
        int K = (int)(log((double)n) / log(2.0));
        for(i=1; i<=n; i++) dp[i][0] = i;
        for(int j=1; j<=K; j++)
            for(i=1; i+mi[j]-1 <= n ; i++)
            {
                int a = dp[i][j-1];
                int b = dp[i+mi[j-1]][j-1];
                if(dep[a] < dep[b]) dp[i][j] = a;
                else                dp[i][j] = b;
            }
    }
    int rmq(int x,int y)
    {
        int k=(int)(log((double)(y-x+1))/log(2.0));
        int a=dp[x][k];
        int b=dp[y-mi[k]+1][k];
        if(dep[a]<dep[b])//最近公共祖先的深度
            return a;
        else
            return b;
    }
    int lca(int a,int b)
    {
        int x=first[a];
        int y=first[b];
        int k;
        if(x>y)//可用swap,但是我以前用了超时,所以再也不敢用了。
        {
            k=rmq(y,x);
            return node[k];
        }
        else
        {
            k=rmq(x,y);
            return node[k];
        }
    }
    
    int main()
    {
        int i,j,n,m,a,b;
        for(i=0;i<20;i++)
            mi[i]=1<<i;
        
        while(scanf("%d",&n)!=EOF)
        {
            memset(in,0,sizeof(in));
            for(i=0;i<=n;i++)
                map[i].clear();
            for(i=0;i<n;i++)
            {
                scanf("%d:(%d)",&a,&m);
                for(j=0;j<m;j++)
                {
                    scanf("%d",&b);
                    map[a].push_back(b);
                    map[b].push_back(a);
                    in[b]++;
                }
                
            }
            
            memset(vis,0,sizeof(vis));
            int tot=0;
            for(i=1;i<=n;i++)
                if(!in[i])
                    dfs(tot,i,1);
                rmq_init(tot);
                scanf("%d",&m);
                getchar();
                memset(lc,0,sizeof(lc));    
                for(i=0;i<m;i++)
                {
                    scanf(" (%d %d)",&a,&b);
                    lc[lca(a,b)]++;
                }
                for(i=1;i<=n;i++)
                {
                    if(lc[i])
                        printf("%d:%d
    ",i,lc[i]);
                }
        }
        return 0;
    }
    /**
    
    */
  • 相关阅读:
    第六课 课程重点(仿站及常见代码用法)
    第七课 课程重点(js、声明变量、数据类型)
    html作业及答案
    【实用代码】选项卡切换——带标题底纹样式
    CSS 样式表(小结)
    各大常用浏览器兼容性代码
    【小练习】“表格”制作及答案
    第一周综合练习
    第五课 课程重点(z-index、overflow、浏览器兼容性)
    当前单元测试主流工具
  • 原文地址:https://www.cnblogs.com/BruceNoOne/p/3215280.html
Copyright © 2020-2023  润新知