zoukankan      html  css  js  c++  java
  • POJ1470 Closest Common Ancestors

    LCA问题,用了离线的tarjan算法。输入输出参考了博客http://www.cnblogs.com/rainydays/archive/2011/06/20/2085503.html
    tarjan算法是用了dfs+并查集的方式做的。这里输入输出有个不错的地方,就是用scanf("%[^0-9]", st);跳过非数字。
    里面用数组g来表示多维的树,还用并查集的id数组的-1来表示是否访问。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    using namespace std;
    
    #define MAXN 909
    
    /*
    g for the edges
    hasroot for whether the node is under root, it helps to identify the root
    id for disjoint-set
    lca for LCA of two nodes
    sum for the count for ancestors in result
    */
    int n, root;
    bool g[MAXN][MAXN], hasroot[MAXN];
    int id[MAXN], lca[MAXN][MAXN];
    int sum[MAXN];
    
    void input()
    {
        int a, b, m;
        char str[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]", str);
            scanf("%d", &m);
            scanf("%[^0-9]", str);
            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;
            }
    }
    
    // for disjoint-set
    int find(int i)
    {
    	if (id[i] == i)
    		return i;
    	return id[i] = find(id[i]);;
    }
    
    void merge(int i, int j)
    {
    	id[find(i)] = find(j);
    }
    
    // do the tarjan algo and update lca table
    void tarjan(int rt)
    {
    	id[rt] = rt;
    	// id[k] != -1 means visited
    	for (int i = 0; i < n; i++)
    		if (g[rt][i] && id[i] == -1)
    		{
    			tarjan(i);
    			merge(i, rt); // the order matters, because of the implementaion of merge
    		}
    	for (int i = 0; i < n; i++)
    		if (id[i] != -1)
    			lca[rt][i] = lca[i][rt] = find(i);
    }
    
    void solve()
    {
    	int m;
        char str[100];
        scanf("%d", &m);
        for (int i =0; i < m; i++)
        {
            int a, b;
            scanf("%[^0-9]", str);
            scanf("%d", &a);
            scanf("%[^0-9]", str);
            scanf("%d", &b);
            a--;
            b--;
            sum[lca[a][b]]++;
        }
        for (int i =0; i < n; i++)
            if (sum[i])
                printf("%d:%d
    ", i + 1, sum[i]);
    }
    
    int main()
    {
    	//freopen("d:\\t.txt", "r", stdin);
    	while (scanf("%d", &n) != EOF)
    	{
    		char str[100];
    		input();
    		memset(id, -1, sizeof(id));
    		memset(sum, 0, sizeof(sum));
    		tarjan(root);
    		solve();
    		scanf("%[^0-9]", str);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    【leetcode】19. Remove Nth Node From End of List
    【leetcode】18. 4Sum
    【leetcode】371. Sum of Two Integers
    【leetcode】17. Letter Combinations of a Phone Number
    【leetcode】16. 3Sum Closest
    【leetcode】13. Roman to Integer
    【leetcode】15. 3Sum
    【leetcode】14. Longest Common Prefix
    【leetcode】368. Largest Divisible Subset
    Linux学习总结(十四) 文件的打包和压缩
  • 原文地址:https://www.cnblogs.com/lautsie/p/3788924.html
Copyright © 2011-2022 走看看