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\n", 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;

}

  

你可能感兴趣的:(close)