poj 1470 Closest Common Ancestors LCA离线

传送门:Closest Common Ancestors

基本的LCA的离线版本,如果不懂请移步LCA

AC Code

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int MXN = 1e3 + 7;
const int MXM = 3e5 + 7;

struct Edge{
    int v,nxt;
}E[MXN<<1];

int e,head[MXN],q;
int ans[MXM],pre[MXN],cnt[MXN];
int ancestor[MXN];
bool flag[MXN],vis[MXN];

int findS(int x)
{
    return (-1 == pre[x]) ? x : (pre[x] = findS(pre[x]));
}
void join(int x,int y)
{
    int fx = findS(x);
    int fy = findS(y);
    if(fx!=fy) pre[fx]  =fy;
}
void add(int u,int v)
{
    E[e].v = v;
    E[e].nxt = head[u];
    head[u] = e++;
    E[e].v = u;
    E[e].nxt = head[v];
    head[v] = e++;
}

struct Query{
    int q,nxt,id;
}query[MXM*2];
int h[MXM<<1];
void addQ(int u,int v,int id)
{
    query[q].q = v;
    query[q].nxt = h[u];
    query[q].id = id;
    h[u] = q++;
    query[q].q = u;
    query[q].nxt = h[v];
    query[q].id = id;
    h[v] = q++;
}
void init()
{
    e = 0;q = 0;
    memset(h,-1,sizeof h);
    memset(flag,0,sizeof flag);
    memset(vis,0,sizeof vis);
    memset(ancestor,0,sizeof ancestor);
    memset(ans,0,sizeof ans);
    memset(pre,-1,sizeof pre);
    memset(cnt,0,sizeof cnt);
    memset(head,-1,sizeof head);
}

void LCA(int u)
{
    ancestor[u] = u;
    vis[u] = true;
    for(int i=head[u];~i;i=E[i].nxt) {
        int v = E[i].v;
        if(vis[v]) continue;
        // cout<<u<<endl;
        LCA(v);
        join(u,v);
        ancestor[findS(u)] = u;
    }
    for(int i=h[u];~i;i=query[i].nxt){
        int v = query[i].q;
        if(vis[v]) {
        //cout<<v<<"---"<<findS(v)<<endl;
            ans[query[i].id] = ancestor[findS(v)];
        //cout<<v<<"----"<<ancestor[findS(v)]<<endl;
        }
    }
}

int main()
{
    int n;//freopen("in.txt","r",stdin);
    while(cin>>n)
    {
        init();
        int u,v,j,Q,k;
        for(int i=1;i<=n;i++) {
            scanf("%d:(%d)",&u,&k);
            while(k--) {
                scanf("%d",&v);
                add(u,v); flag[v] = true;
            }
        }
        scanf("%d",&Q);
        for(int i=0;i<Q;i++) {
            char ch;cin>>ch;
            scanf("%d %d)",&u,&v);
            addQ(u,v,i);
        }
        int rt;
        for(int i=1;i<=n;i++) {
            if(!flag[i]) {rt=i;break;}
        }
        LCA(rt);
        for(int i=0;i<Q;i++) cnt[ans[i]] ++;
        for(int i=1;i<=n;i++) {
            if(!cnt[i]) continue;
            printf("%d:%d\n",i,cnt[i]);

        }
    }
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值