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;
}
/**

*/
原文地址:https://www.cnblogs.com/BruceNoOne/p/3215280.html