zoukankan      html  css  js  c++  java
  • poj1470

    题意:基本的lca问题

    分析:lca的离线算法为tarjan,tarjan算法的流程如下。dfs遍历树,节点a在遍历完成之后退回到a在树中的父亲节点,然后a在并查集中的father指针会指向这个父亲节点。也就是说一个节点,所有以它的被遍历过的直接子节点为根的子树中的点都会在并查集中被合并到这个点,并以它作为代表元。最开始每个点自己一个集合,每次合并操作都是伴随着遍历中的退后行为进行的。这样就产生了一个性质,在遍历过程中,一个被遍历过的节点的集合代表元在哪,取决于由树根到该节点的路径上我退后到了哪个节点。这样一来,所有遍历过的节点与当前节点的lca也恰好就是它们的代表元了。在遍历离开当前点之前,先将所有遍历过的点与当前点的lca在二维数组中记录下来。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    using namespace std;
    
    #define maxn 909
    
    int n, root;
    bool g[maxn][maxn], hasroot[maxn];
    int id[maxn], lcs[maxn][maxn];
    int sum[maxn];
    
    void input()
    {
        int a, b, m;
        char st[100];
        memset(g, 0, sizeof(g));
        memset(hasroot, 0, sizeof(hasroot));
        for (int i =0; i < n; i++)
        {
            scanf("%d", &a);
            a--;
            scanf("%[^0-9]", st);
            scanf("%d", &m);
            scanf("%[^0-9]", st);
            for (int i =0; i < m; i++)
            {
                scanf("%d", &b);
                b--;
                hasroot[b] =true;
                g[a][b] = g[b][a] =true;
            }
        }
        for (int i =0; i < n; i++)
            if (!hasroot[i])
            {
                root = i;
                break;
            }
    }
    
    int get(int i)
    {
        if ((id[i] == i))
            return i;
        return id[i] =get(id[i]);
    }
    
    void unin(int i, int j)
    {
        id[get(i)] =get(j);
    }
    
    void dfs(int rt)
    {
        int i;
        id[rt] = rt;
        for (i =0; i < n; ++i)
            if (g[rt][i] &&-1== id[i])
            {
                dfs(i);
                unin(i, rt);
            }
        for (i =0; i < n; ++i)
            if (-1!= id[i])
                lcs[rt][i] = lcs[i][rt] =get(i);
    }
    
    void work()
    {
        int m;
        char st[100];
        scanf("%d", &m);
        for (int i =0; i < m; i++)
        {
            int a, b;
            scanf("%[^0-9]", st);
            scanf("%d", &a);
            scanf("%[^0-9]", st);
            scanf("%d", &b);
            a--;
            b--;
            sum[lcs[a][b]]++;
        }
        for (int i =0; i < n; i++)
            if (sum[i])
                printf("%d:%d\n", i +1, sum[i]);
    }
    
    int main()
    {
        //freopen("t.txt", "r", stdin);
        char st[100];
        while (scanf("%d", &n) != EOF)
        {
            input();
            memset(id, -1, sizeof(id));
            memset(sum, 0, sizeof(sum));
            dfs(root);
            work();
            scanf("%[^0-9]", st);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    jquery ajax 跨域请求【原】
    纯js异步无刷新请求(只支持IE)【原】
    正则表达式高级用法【原】
    所有HTTP请求参数及报文查看SERVLET【原】
    AES加密【转】
    Object.prototype.toString.call() 区分对象类型
    js中的preventDefault与stopPropagation详解
    在项目中如何利用分页插件呢?
    Iframe 在项目中的使用总结
    在项目中那个少用if else 语句,精简代码,便于维护的方法(1)
  • 原文地址:https://www.cnblogs.com/rainydays/p/2085503.html
Copyright © 2011-2022 走看看