poj1470Closest Common Ancestors(LCA模版)

就是一个板子,sum[lca(u, v)]++就好了。

const int LOGN = 11;
const int maxn = 1 << LOGN;
int head[maxn], nxt[maxn], pnt[maxn], ecnt;
int sum[maxn], mark[maxn];
int dep[maxn];
int fa[LOGN][maxn];
void addedge(int u,int v) {
    pnt[ecnt] = v, nxt[ecnt] = head[u], head[u] = ecnt++;
}
int n, m;
void dfs(int u,int pre,int depth) {
    fa[0][u] = pre;
    dep[u] = depth;
    for (int i = head[u];~i;i = nxt[i]) {
        int v = pnt[i];
        if (v == pre) continue;
        dfs(v, u, depth + 1);
    }
}
void build() {
    for (int k = 0;k < LOGN - 1;++k) {
        for (int u = 1;u <= n;++u) {
            if (fa[k][u] == -1) fa[k+1][u] = -1;
            else fa[k+1][u] = fa[k][fa[k][u]];
        }
    }
}
inline int upslope(int u,int p) {
    for (int k = 0;k < LOGN - 1;++k)
        if ((p >> k) & 1) u = fa[k][u];
    return u;
}
inline int lca(int u,int v) {
    if (dep[u] < dep[v]) swap(u, v);
    u = upslope(u, dep[u] - dep[v]);
    if (u == v) return u;
    for (int k = LOGN - 1;k >= 0;--k) {
        if (fa[k][u] != fa[k][v])
            u = fa[k][u], v = fa[k][v];
    }
    return fa[0][u];
}
int main(int argc, const char * argv[])
{    
    // freopen("in.txt","r",stdin);
    // freopen("out.txt","w",stdout);
    // clock_t _ = clock();

    while(scanf("%d", &n) != EOF) {
        memset(head, -1,sizeof head), ecnt = 0;
        int u, v, num;
        memset(mark, 0,sizeof mark);
        for (int i = 1;i <= n;++i) {
            scanf("%d:(%d)", &u, &num);
            while(num--) {
                scanf("%d", &v);
                addedge(u, v), addedge(v, u);
                mark[v] = 1;
            }
        }
        scanf("%d", &m);
        memset(sum, 0,sizeof sum);
        for (int i = 1;i <= n;++i) {
            if (!mark[i]) {
                dfs(i, -1, 0);
                break;
            }
        }
        build();
        while(m--) {
            while(getchar() != '(');
            scanf("%d%d", &u, &v);
            sum[lca(u, v)]++;
            while(getchar() != ')');
        }
        for (int i = 1;i <= n;++i)
            if (sum[i]) printf("%d:%d\n",i, sum[i]);
    }

    // printf("\nTime cost: %.2fs\n", 1.0 * (clock() - _) / CLOCKS_PER_SEC);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值