本题也是找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\n", it->first, it->second);
}
}
return 0;
}