您的位置:首页 > 其它

tarjan离线算法-LCA最近公共祖先算法模板(详细)

2015-05-05 22:00 513 查看
/********************************************/

/*****LCA最近公共祖先离线算法(tarjan)*****/

/********************************************/

#include <iostream>

#include <vector>

#include <cstdio>

#include <cstring>

using namespace std;

const int MAX=1010;

int n,m;///n代表树中节点个数,m代表查询的个数

int tree_root;///树根节点

vector<int> d[MAX];///保存树

vector<int> q[MAX];///保存查询内容

int ancestor[MAX];///保存某个集合中所有元素的最近公共祖先

bool f[MAX];///标志某个节点是否被访问过

struct node

{

int x;

int y;

} query[MAX]; ///保存查询顺序

int ans[MAX][MAX];///保存查询结果

/***************并查集代码*********************/

int par[MAX];///记录某个节点所在的集合

int ranks[MAX];///记录集合树的深度

void make_set()

{

for(int i=1; i<=n; i++)

{

par[i]=i;

ranks[i]=0;

}

}

int find_set(int x)

{

if(x!=par[x])

par[x]=find_set(par[x]);

return par[x];

}

void union_set(int x,int y)

{

x=find_set(x);

y=find_set(y);

if(x==y)

return;

if(ranks[x]>ranks[y])

par[y]=x;

else

{

par[x]=y;

if(ranks[x]==ranks[y])

ranks[y]++;

}

}

void built_tree() ///建树

{

for(int i=1; i<=n; i++)

d[i].clear();

memset(f,0,sizeof(f));

int x,y;

for(int i=1; i<=n-1; i++)

{

scanf("%d%d",&x,&y);

d[x].push_back(y);

f[y]=true;///求根节点

}

for(int i=1; i<=n; i++)

{

if(!f[i])

{

tree_root=i;

break;

}

}

}

void built_query() ///保存查询

{

for(int i=1; i<=n; i++)

q[i].clear();

int x,y;

for(int i=1; i<=m; i++)

{

scanf("%d%d",&x,&y);

query[i].x=x;

query[i].y=y;

q[x].push_back(y);

q[y].push_back(x);///此处应该注意

}

}

void tarjan(int root) ///在深搜过程中求解问题

{

ancestor[root]=root;///设置root所在集合的元素的最近公共祖先为root

int len=d[root].size();

for(int i=0; i<len; i++)

{

tarjan(d[root][i]);

union_set(root,d[root][i]);///合并root与其子节点

ancestor[find_set(root)]=root;///把合并后的集合的最近公共祖先设为root

}

f[root]=true;

len=q[root].size();

for(int i=0; i<len; i++)

{

if(f[q[root][i]])

ans[root][q[root][i]]=ancestor[find_set(q[root][i])];///保存查询结果

}

}

void print_query()

{

for(int i=1; i<=m; i++)

{

if(ans[query[i].x][query[i].y]!=0)

printf("%d %d的最近公共祖先是%d\n",query[i].x,query[i].y,ans[query[i].x][query[i].y]);

else

printf("%d %d的最近公共祖先是%d\n",query[i].x,query[i].y,ans[query[i].y][query[i].x]);

}


}

int main()

{

int T;///测试案例个数

scanf("%d",&T);

for(int i=1; i<=T; i++)

{

scanf("%d%d",&n,&m);

built_tree();

built_query();

memset(f,0,sizeof(f));

make_set();

tarjan(tree_root);

print_query();

}

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: