zoukankan      html  css  js  c++  java
  • POJ 1470 Closest Common Ancestors LCA题解

    本题也是找LCA的题目,只是要求多次查询。一般的暴力查询就必定超时了,故此必须使用更高级的方法,这里使用Tarjan算法。

    本题处理Tarjan算法,似乎输入处理也挺麻烦的。

    注意: 由于查询的数据会极大,故此使用一个数组记录全部查询数据就会超时的。

    我就载在这里了。查了好久才想到这点。

    由于我使用了一个vector容器记录了查询数据。故此每次都循环这组这么大的数据,就超时了。

    ----解决的方法:使用一个vector<int> quest来记录查询数组。这样每次都仅仅须要循环某节点的邻接查询点就能够了。数据量是非常小的。

    有些说法没道理的:比方:结尾是否有空格?没有!

    我使用了按权值查询并查集的优化,实验证明:没有优化效果。

    使用map容器记录结果,好像没有加速,只是这种代码更加成熟。

    其它就是Tarjan算法了,网上也不少讲解的了,结合代码学习,这个算法也不难。


    #include <stdio.h>
    #include <vector>
    #include <string.h>
    #include <algorithm>
    #include <map>
    using namespace std;
    
    struct Node
    {
    	bool notRoot;
    	bool vis;
    	vector<int> child;
    };
    
    const int MAX_N = 901;
    int N, u, v, n;
    Node Tree[MAX_N];
    //vector<int> quest;//这样记录就会超时,应该是由于须要查询的数据极其大,所以引发超时
    vector<int> quest[MAX_N];
    map<int, int> ans;
    int par[MAX_N];
    int rank[MAX_N];
    int ancestor[MAX_N];
    
    void init(int n)
    {
    	for (int i = 1; i <= n; i++)
    	{
    		Tree[i].child.clear();
    		Tree[i].notRoot = false;
    		Tree[i].vis = false;
    		quest[i].clear();
    	}
    }
    
    int find(int x)
    {
    	if (!par[x]) return x;
    	return par[x] = find(par[x]);
    }
    
    void unionTwo(int x, int y)
    {
    	x = find(x);
    	y = find(y);
    	if (x == y) return;
    	if (rank[x] < rank[y]) par[x] = y;
    	else
    	{
    		par[y] = x;
    		rank[x]++;
    	}
    }
    
    void LCATarjan(int r)
    {
    	//ancestor[r] = r;
    	for (int i = 0; i < (int)Tree[r].child.size(); i++)
    	{
    		int v = Tree[r].child[i];
    		//if (Tree[v].vis) continue;
    		LCATarjan(v);
    		unionTwo(r, v);
    		ancestor[find(r)] = r;
    	}
    	Tree[r].vis = true;
    	for (int i = 0; i < (int)quest[r].size(); i++)
    	{
    		int v = quest[r][i];
    		if (Tree[v].vis) ans[ancestor[find(v)]]++;
    	}
    }
    
    int main()
    {
    	while (scanf("%d", &N) != EOF)
    	{
    		init(N);
    		memset(par, 0, sizeof(int) * (N+1));
    		memset(ancestor, 0, sizeof(int) * (N+1));
    		memset(rank, 0, sizeof(int) * (N+1));
    
    		for (int i = 0; i < N; i++)
    		{
    			scanf("%d", &u);
    			while (getchar() != '(') ;
    			scanf("%d", &n);
    			while (getchar() != ')') ;
    			for (int j = 0; j < n; j++)
    			{
    				scanf("%d", &v);
    				Tree[u].child.push_back(v);
    				Tree[v].notRoot = true;
    			}
    		}		
    
    		scanf("%d", &n);
    		for (int i = 0; i < n; i++)
    		{
    			char a = getchar();
    			while (a != '(') a = getchar();
    			u = 0;
    			a = getchar();
    			while (a != ' ')
    			{
    				u = (u <<3) + (u<<1) + (a - '0');
    				a = getchar();
    			}
    			v = 0;
    			a = getchar();
    			while (a != ')')
    			{
    				v = (v<<3) + (v<<1) + (a - '0');
    				a = getchar();
    			}
    			quest[u].push_back(v);
    			quest[v].push_back(u);
    		}
    
    		int root = 0;
    		for (int i = 1; i <= N; i++)
    		{
    			if (!Tree[i].notRoot)
    			{
    				root = i;
    				break;
    			}
    		}
    		ans.clear();
    		LCATarjan(root);
    		
    		map<int, int>::iterator it;
    		for (it = ans.begin(); it != ans.end(); it++)
    		{
    			printf("%d:%d
    ", it->first, it->second);
    		}
    	}
    	return 0;
    }




  • 相关阅读:
    day4递归原理及实现
    day4装饰器
    day4迭代器&生成器&正则表达式
    open()函数文件操作
    Python中的内置函数
    function(函数)中的动态参数
    copy深浅拷贝
    collections模块
    set集合
    字典dict常用方法
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/5371401.html
Copyright © 2011-2022 走看看