zoukankan      html  css  js  c++  java
  • POJ 1470 Closest Common Ancestors【LCA Tarjan】

    题目链接:

    http://poj.org/problem?id=1470

    题意:

    给定若干有向边,构成有根数,给定若干查询,求每个查询的结点的LCA出现次数。

    分析:

    还是很裸的tarjan的LCA。
    这题我真的要吐槽!!调试了好久啊!!不是MLE就是RE。。。。

    1. 查询数量没给,所以要用矩阵来存,这样还可以避免重复。
    2. 给边的时候不知道会不会有重复的点,所以讲道理应该用vector保存。
    3. getchar。。。我不知道为什么会RE。。。
    4. 其实ance数组可以不用的,只要每次处理子树的时候pa[v] = u即可。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<iostream>
    using namespace std;
    #define mem(a, b) memset(a, b, sizeof(a))
    #define fuck cout<<"fuck"<<endl;
    const int maxn = 1100;
    vector<int>G[maxn];
    int pa[maxn];
    bool vis[maxn];
    bool in[maxn];
    int ance[maxn];
    int cnt[maxn];
    int root, n, tot;
    int query[maxn][maxn];
    int _find(int x)
    {
        if(pa[x] != x) return pa[x] = _find(pa[x]);
        return x;
    }
    void unite(int x, int y)
    {
        int rx = _find(x), ry = _find(y);
        if(rx == ry) return;
        pa[rx] = ry;
    }
    void init()
    {
       for(int i = 1; i <= n; i++){
            G[i].clear();
            pa[i] = i;
       }
        mem(ance, 0);
        mem(vis, false);
        mem(query, 0);mem(cnt, 0);
        mem(in, false);
    }
    void LCA(int u)
    {
        ance[u] = u;
        for(int i = 0; i < G[u].size(); i++){
            int v = G[u][i];
            LCA(v);
            unite(u, v);
            ance[_find(u)] = u;
        }
        vis[u] = true;
        for(int i = 1; i <= n; i++){
            if(vis[i] && query[u][i]) cnt[ance[_find(i)]] += query[u][i];
        }
    }
    int main(void)
    {
        int u, v, k;
        int Q;
        while(~scanf("%d",&n)){
            init();
            for(int i = 0; i < n; i++){
              scanf("%d:(%d)",&u,&k);
                while(k--){
                    scanf("%d",&v);
                    in[v] = true;
                    G[u].push_back(v);
                }
            }
            scanf("%d",&Q);
            for(int i = 0; i < Q; i++){
                scanf(" (%d %d)",&u,&v);
                query[u][v]++;
                query[v][u]++;
            }
            for(root = 1; root <= n; root++){
                if(!in[root]) break;
            }
            LCA(root);
            for(int i = 1; i <= n ; i++)
                if(cnt[i]) printf("%d:%d
    ",i, cnt[i]);
        }
        return 0;
    }
    
  • 相关阅读:
    文档对象模型(DOM)
    Gridview,DataList,Repeater 鼠标经过时行颜色变换
    一组经典测试思想观点
    如何编写测试计划
    测试用例 之我见
    软件测试流程 之我见
    经典博文各系列文章
    JS实现在Repeater控件中创建可隐藏区域
    测试感想
    海量数据处理 算法总结
  • 原文地址:https://www.cnblogs.com/Tuesdayzz/p/5758697.html
Copyright © 2011-2022 走看看