POJ 1330 Nearest Common Ancestors LCA

来源:互联网 发布:深圳网络教育有哪些 编辑:程序博客网 时间:2024/05/16 18:18

题目:http://poj.org/problem?id=1330


题意:一棵n个点的数,输入n - 1条边,最后输入一组查询,求它们的最近公共祖先


思路:tarjan算法求LCA第一题,模板题


总结:tarjan求强连通,tarjan求双联通,tarjan求LCA,粗糙的学完了。。。

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int N = 10010;typedef long long ll;struct edge{    int to, cost, next;} G1[N], G2[N];int head1[N], head2[N], par[N];int cnt1, cnt2;bool vis[N], deg[N];int n, m;void init(){    for(int i = 1; i <= n; i++)        par[i] = i;    memset(head1, -1, sizeof head1);    memset(head2, -1, sizeof head2);    memset(deg, 0, sizeof deg);    memset(vis, 0, sizeof vis);    cnt1 = cnt2 = 0;}void add_edge1(int v, int u){    G1[cnt1].to = u;    G1[cnt1].next = head1[v];    head1[v] = cnt1++;}void add_edge2(int v, int u){    G2[cnt2].to = u;    G2[cnt2].next = head2[v];    head2[v] = cnt2++;}int ser(int x){    int r = x, i = x, j;    while(r != par[r]) r = par[r];    while(i != r) j = par[i], par[i] = r, i = j;    return r;}void tarjan_lca(int v){    int u;    for(int i = head1[v]; i != -1; i = G1[i].next)    {        u = G1[i].to;        tarjan_lca(u);        par[u] = v;    }    vis[v] = true; /*这个标记的位置很巧妙,求LCA时不能放在函数首部,否则会重复输出某些答案*/    for(int i = head2[v]; i != -1; i = G2[i].next)        if(vis[u = G2[i].to])        {            printf("%d\n", ser(u));            return;        }}int main(){    int t, a, b;    scanf("%d", &t);    while(t--)    {        scanf("%d", &n);        init();        for(int i = 0; i < n - 1; i++)        {            scanf("%d%d", &a, &b);            add_edge1(a, b);            deg[b] = true;        }        scanf("%d%d", &a, &b);        add_edge2(a, b);        add_edge2(b, a);        for(int i = 1; i <= n; i++)            if(! deg[i]) /*树根*/            {                tarjan_lca(i);                break;            }    }    return 0;}




0 0