zoukankan      html  css  js  c++  java
  • 最近公共祖先

    1. 离线算法

    http://hihocoder.com/problemset/problem/1067

    并查集

    #define _CRT_SECURE_NO_WARNINGS
    #include<stdio.h>
    #include<string.h>
    #define N 100005
    int firCh[N], firQuery[N], set[N], cnt = 0, nm = 0;
    char Name[N][100];
    bool visit[N];
    struct node
    {
        int to;
        int next;
    };
    node Ch[N];
    struct query
    {
        int to;
        int next;
        int ans;
    };
    query Query[N<<2];
    struct nam
    {
        int num; //编号
        int next[60]; //>'z'-'A'+26
    };
    nam name[N << 5];
    
    int getNum(char *s)
    {
        int len = strlen(s), k = 0, c;
        for (int i = 0; i < len; i++)
        {
            c = s[i] - 'A';
            if (0 == name[k].next[c])
                name[k].next[c] = ++cnt;
            k = name[k].next[c];
        }
        if (0 == name[k].num)
            name[k].num = ++nm;
        return name[k].num;
    }
    
    int findPa(int n)
    {
        if (set[n] != n)
            set[n] = findPa(set[n]);
        return set[n];
    }
    
    void dfs(int n)
    {
        visit[n] = 1;
        int t, i;
        for (i = firCh[n]; i != 0; i = Ch[i].next)
        {
            t = Ch[i].to;
            dfs(t);
            set[t] = n;
        }
        for (i = firQuery[n]; i != 0; i = Query[i].next)
        {
            t = Query[i].to;
            if (visit[t])
            {
                int q = (i % 2) ? (i) : (i - 1);
                Query[q].ans = findPa(t);
            }
        }
    }
    
    int main()
    {
        int n, m, n1, n2, num, i;
        char s1[100], s2[100];
        memset(firCh, 0, sizeof(firCh));
        scanf("%d", &n);
        for (num = 0, i = 0; i < n; i++)
        {
            scanf("%s%s", s1, s2);
            n1 = getNum(s1);
            n2 = getNum(s2);
            if (0 == Name[n1][0])
                strcpy(Name[n1], s1);
            if (0 == Name[n2][0])
                strcpy(Name[n2], s2);
            Ch[++num].to = n2;
            Ch[num].next = firCh[n1];
            firCh[n1] = num;
        }
        memset(firQuery, 0, sizeof(firQuery));
        scanf("%d", &m);
        for (num = 0, i = 0; i < m; i++)
        {
            scanf("%s%s", s1, s2);
            n1 = getNum(s1);
            n2 = getNum(s2);
            Query[++num].to = n2;
            Query[num].next = firQuery[n1];
            firQuery[n1] = num;
            Query[++num].to = n1;
            Query[num].next = firQuery[n2];
            firQuery[n2] = num;
        }
        for (i = 0; i < n; i++)
            set[i] = i;
        memset(visit, 0, sizeof(visit));
        dfs(1);
        for (i = 0; i < m; i++)
            printf("%s
    ", Name[Query[i*2+1].ans]); 
    
        return 0;
    }

    2. 在线算法

    http://hihocoder.com/problemset/problem/1069

    求每个结点所在层数,先序遍历树记录路径,用rmq数组记录区间内最小层数(rmq[i][j]表示从第i个结点开始长度为2^j的区间内的高度最小值)。

    #define _CRT_SECURE_NO_WARNINGS
    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    #define N 100005
    char name[N][100];
    int chNum = 0, nameCnt = 0, nameNum = 0, firCh[N], h[N], height = 0, trvs[N << 1], num = 0, rmq[N<<1][20];
    bool v[N];
    
    struct nam
    {
        int num;
        int next[60];
    };
    nam Name[N << 5];
    
    struct node
    {
        int to;
        int next;
    };
    node Ch[N];
    
    int getNum(char *s)
    {
        int len = strlen(s), c, k, i;
        for (i = 0, k = 0; i < len; i++)
        {
            c = s[i] - 'A';
            if (0 == Name[k].next[c])
                Name[k].next[c] = ++nameCnt;
            k = Name[k].next[c];
        }
        if (0 == Name[k].num)
            Name[k].num = ++nameNum;
        return Name[k].num;
    }
    
    int dfs(int k)
    {
        v[k] = 1;
        h[k] = ++height;
        trvs[++num] = k;
        for (int i = firCh[k]; i; i = Ch[i].next)
        {
            dfs(Ch[i].to);
            trvs[++num] = k;
        }
        height--;
        return 0;
    }
    
    int calRMQ(int n) //rmq数组存的是区间内层数最小的结点的nameNum
    {
        int i, j;
        for (i = 1; i <= n; i++)
            rmq[i][0] = trvs[i];
        for (i = 1; (1 << i) <= n; i++)
        {
            for (j = 1; (j + (1 << i)) <= (n + 1); j++)
            {
                int t1 = rmq[j][i - 1], t2 = rmq[j + (1 << (i - 1))][i - 1];
                if (h[t1] <= h[t2])
                    rmq[j][i] = t1;
                else
                    rmq[j][i] = t2;
            }
        }
        return 0;
    }
    
    int find(int *p, int pos, int len)
    {
        for (int i = len; i > 0; i--)
        {
            if (pos == p[i])
                return i;
        }
        return 0;
    }
    
    int getFa(int n1, int n2)
    {
        if (n1 == n2)
            return n1;
        int p1, p2;
        p1 = find(trvs, n1, num);
        p2 = find(trvs, n2, num);
        if (p1 > p2)
        {
            p1 = p1^p2;
            p2 = p1^p2;
            p1 = p1^p2;
        }
        int t = (int)(log((float)(p2 - p1)) / log(2.0));
        int t1 = rmq[p1][t], t2 = rmq[p2 - (1 << t) + 1][t];
        if (h[t1] < h[t2])
            return t1;
        else
            return t2;
    }
    
    int main()
    {
        int n, m, n1, n2, i;
        char s1[100], s2[100];
        scanf("%d", &n);
        for (i = 0; i < n; i++)
        {
            scanf("%s%s", s1, s2);
            n1 = getNum(s1);
            n2 = getNum(s2);
            if (!name[n1][0])
                strcpy(name[n1], s1);
            if (!name[n2][0])
                strcpy(name[n2], s2);
            Ch[++chNum].to = n2;
            Ch[chNum].next = firCh[n1];
            firCh[n1] = chNum;
        }
        memset(v, 0, sizeof(v));
        dfs(1);
    //    for (i = 1; i <= num; i++)
    //        printf("%d ", trvs[i]);
    //    printf("
    ");
        calRMQ(num);
        scanf("%d", &m);
        for (i = 0; i < m; i++)
        {
            scanf("%s%s", s1, s2);
            n1 = getNum(s1);
            n2 = getNum(s2);
            int fa = getFa(n1, n2);
            printf("%s
    ", name[fa]);
            //printf("%d
    ", fa);
        }
    
        return 0;
    }
  • 相关阅读:
    Riverside Curio
    bzoj1010 [HNOI2008]玩具装箱toy
    bzoj1898 [Zjoi2005]Swamp 沼泽鳄鱼
    hdu 5435 A serious math problem
    poj2411 Mondriaan's Dream
    bzoj3450 Tyvj1952 Easy
    关于欧拉函数与莫比乌斯函数等一系列积性函数的线性筛
    NOIP后一波总结
    回忆一下电子科技大学春令营
    【算法】背包九讲
  • 原文地址:https://www.cnblogs.com/argenbarbie/p/5364997.html
Copyright © 2011-2022 走看看