zoukankan      html  css  js  c++  java
  • 【POJ 1330 Nearest Common Ancestors】LCA问题 Tarjan算法

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

    题意:给定一个n个节点的有根树,以及树中的两个节点u,v,求u,v的最近公共祖先。

    数据范围:n [2, 10000]

    思路:从树根出发进行后序深度优先遍历,设置vis数组实时记录是否已被访问。

    每遍历完一棵子树r,把它并入以r的父节点p为代表元的集合。这时判断p是不是所要求的u, v节点之一,如果r==u,且v已访问过,则lca(u, v)必为v所属集合的代表元。p==v的情况类似。

    我的第一道LCA问题的Tarjan算法,题目只有唯一的一组查询,实现起来非常简洁。

    注意题目给树的格式:给出n-1个数对<u, v>,u为v的父节点。因此可以当作有向图用邻接表存储,同时记录各个节点的入度,入度为0的点为树根。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <vector>
     4 using namespace std;
     5 const int MAX_N = 10005;
     6 
     7 int parent[MAX_N];
     8 
     9 void init(){
    10     for(int i=0; i<MAX_N; i++){
    11         parent[i] = i;
    12     }
    13 }
    14 int find(int x){
    15     if(parent[x] == x) return x;
    16     return parent[x] = find(parent[x]);
    17 }
    18 void unite(int x, int y){
    19     x = find(x);
    20     y = find(y);
    21     if(x == y) return ;
    22     parent[y] = x;
    23 }
    24 bool same(int x, int y){
    25     return find(x) == find(y);
    26 }
    27 
    28 vector<int> G[MAX_N];
    29 int u, v;
    30 int T;
    31 int n;
    32 int vis[MAX_N];
    33 int indeg[MAX_N];
    34 
    35 void dfs(int r){
    36     //printf("%d
    ", r);
    37     for(int i=0; i<G[r].size(); i++){
    38         if(!vis[G[r][i]]){
    39             dfs(G[r][i]);
    40             unite(r, G[r][i]);//孩子合并到父节点 
    41         }
    42     }
    43     vis[r] = 1; //后序遍历
    44     if(r == u && vis[v]){
    45         printf("%d
    ", find(v));
    46         return ;
    47     }else if(r == v && vis[u]){
    48         printf("%d
    ", find(u));
    49         return ;
    50     }
    51 }
    52 
    53 void lca(){
    54     memset(vis, 0, sizeof(vis));
    55     init();
    56     int r = 0;
    57     for(int i=1; i<=n; i++){
    58         if(indeg[i]==0){
    59             //printf("root : %d
    ", i); //入度为0的是树根 
    60             dfs(i);
    61         }
    62     }     
    63 }
    64 
    65 int main()
    66 {
    67     freopen("1330.txt", "r", stdin);
    68     scanf("%d", &T);
    69     while(T--){
    70         scanf("%d", &n);
    71         memset(indeg, 0, sizeof(indeg));
    72         for(int i=0; i<MAX_N; i++) G[i].clear();
    73         for(int i=0; i<n-1; i++){
    74             scanf("%d%d", &u, &v);
    75             G[u].push_back(v);//有向图 
    76             indeg[v]++;
    77         }
    78         scanf("%d%d", &u, &v);
    79         lca();
    80     }
    81     return 0;
    82 }
  • 相关阅读:
    区块链入门
    上海美食餐厅
    《OD学hadoop》20160910某旅游网项目实战
    《OD学hadoop》20160904某旅游网项目实战
    《OD学hadoop》20160903某旅游网项目实战
    qt5-自定义类
    qt5-Qt Creator使用
    qt5-QPushButton按钮
    qt5-工程文件的介绍--快捷键
    电路分析-电阻
  • 原文地址:https://www.cnblogs.com/helenawang/p/5503784.html
Copyright © 2011-2022 走看看