您的位置:首页 > 其它

LCA最近公共祖先——tarjan算法

2012-05-12 16:33 330 查看
tarjan算法求最近公共祖先,理论详见http://www.nocow.cn/

#include <iostream>
#include <fstream>
using namespace std;
/**
LCA 最近公共祖先 tarjan算法
并查集+dfs
离线算法 先读入所有查询问题,并不按顺序给出结果。
算法流程
I.  vis[i]记录节点i是否被访问。
首先进行dfs,tarjan(i)。
置vis[i] = 1,father[i] = i。
II. 对所有与节点i有关的查询(i,j)进行查询处理
若节点已经访问了,vis[j] == 1,则可以找到(i,j)的LCA。
LCA(i,j) = getfather(j)。
III.对所有节点i的儿子j,若vis[j] == 0
则tarjan(j);
且father[j] = i;
**/
int vis[100],adj[100][100],n,m,q,father[100],que[100][100],anc[100][100];
long adj_len[100],que_len[100];
long find(long i)
{
if(father[i] == i) return i;
else return find(father[i]);
}
void tarjan(long i)
{
long j;
vis[i] = 1;
father[i] = i;
/**先处理与i有关的查询**/
for(j=1;j<=que_len[i];j++)
if(vis[que[i][j]] == 1)
{
anc[i][que[i][j]] = find(que[i][j]);
cout<<i<<" "<<que[i][j]<<" "<<anc[i][que[i][j]]<<endl;
}
/**再处理i的所有儿子**/
for(j=1;j<=adj_len[i];j++)
if(vis[adj[i][j]] == 0)
{
tarjan(adj[i][j]);
father[adj[i][j]] = father[i];          /**此处要更新father[j]!!!**/
}
return;
}
int main()
{
ifstream fin("d.in");
long i,j,k,t;
fin>>n;
memset(adj_len,0,sizeof(adj_len));
memset(adj,0,sizeof(adj));
memset(que_len,0,sizeof(que_len));
memset(que,0,sizeof(que));

for(i=1;i<=n;i++)
{
fin>>m>>k;
for(j=1;j<=k;j++)
{
fin>>t;
adj[m][++adj_len[m]] = t;
}
}
fin>>q;
for(i=1;i<=q;i++)
{
fin>>j>>k;
que[j][++que_len[j]] = k;
que[k][++que_len[k]] = j;
}

tarjan(1);

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