午时刷题,难甚,遂小憩于桌上,惊醒,于梦中有所得,虽大声曰:吾已得tarjan之奥秘!

关于tarjan算法,其实就是一个递归加并查集的应用。

大致代码:

#include<bits/stdc++.h>
using namespace std;
int find(int x){
....
} void join(int x,int y)
{
....
}
void dfs(int x)
{
int len=v[x].size();
for(int i=; i<len; i++) //遍历x的子节点
{
dfs(v[x][i]); //继续往下推
join(v[x][i],x); //将x的所有子节点的祖先都设为x
}
vis[x] = true; //证明x走过了
for(int i=; i<=n; i++) //对每个x循环1~n
if(vis[i]&&g[x][i]) //如果i已经走过并且要求(x,i)
ans=find(i); //lca就是ans
}

由以上代码可以看出,tarjan实际上就是并查集与dfs的结合,其最核心的部分就是dfs那部分

只要理解了dfs()的内容,就能理解tarjan

而对于dfs函数,我们首先就会想到它的特性:不撞南墙不回头。

假如有一颗树,对其dfs,那么首先它会沿着一个分支一直到尽头(如图):

而当走到4这个点时,函数开始执行下列语句:

join(v[x][i],x);        //将x的所有子节点的祖先都设为x 
//而此时pre[4]=3;pre[3]=3;pre[2]=2;pre[1]=1;

再然后是:

 vis[x] = true;              //证明x走过了
for(int i=1; i<=n; i++) //对每个x循环1~n
if(vis[i]&&g[x][i]) //如果i已经走过并且要求(x,i)
ans=find(i); //lca就是ans
}
如果存在要求lca[x][i],先看i点是否走过,如果走过,那就只有一种可能(真相只有一个!真実はいつも一つ):

i,k必在两条不同分支上,并且交于某个点x,如果i已经走过了,那么,i所在的这条分支上所有的点都有明确的父子关系,即find(i)==x!
代码参上:
#pragma GCC optimize(2)
#include<stdio.h>
#include<string.h>
#include<vector>
#define M 1007
using namespace std;
int g[M][M],in[M],pre[M],cnt[M];
bool vis[M];
vector<int>v[M];
int n,m;
void init()
{
memset(g,,sizeof(g));
memset(in,,sizeof(in));
memset(cnt,,sizeof(cnt));
memset(vis,false,sizeof(vis));
for(int i=; i<=n; i++)
{
v[i].clear();
pre[i]=i;
}
}
int fond(int x)
{
return x==pre[x]?x:pre[x]=fond(pre[x]);
}
void join(int x,int y)
{
int xx=fond(x);
int yy=fond(y);
pre[xx]=yy;
}
void dfs(int x)
{
int len=v[x].size();
for(int i=; i<len; i++) //遍历x的子节点
{
dfs(v[x][i]); //继续往下推
join(v[x][i],x); //将x的所有子节点的祖先都设为x
}
vis[x] = true; //证明x走过了
for(int i=; i<=n; i++) //对每个x循环1~n
if(vis[i]&&g[x][i]) //如果i已经走过并且要求(x,i)
cnt[fond(i)]+=g[x][i]; //
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
init();
int a,b,c,root;
for(int i=; i<=n; i++)
{
scanf("%d:(%d)",&a,&b);
while(b--)
{
scanf(" %d",&c);
v[a].push_back(c);
in[c]++;
}
}
scanf("%d",&m);
getchar();
while(m--)
{
scanf("(%d,%d)",&a,&b);
getchar();
g[a][b]++;
g[b][a]++;
}
for(int i=; i<=n; i++)
if(!in[i])
{
root=i;
break;
}
dfs(root);
for(int i=; i<=n; i++)
{
if(cnt[i])
printf("%d\n",i);
}
}
return ;
}
以上;

Closest Common Ancestors (Lca,tarjan)的更多相关文章

  1. poj 1470 Closest Common Ancestors LCA

    题目链接:http://poj.org/problem?id=1470 Write a program that takes as input a rooted tree and a list of ...

  2. POJ1470 Closest Common Ancestors 【Tarjan的LCA】

    非常裸的模版题,只是Tarjan要好好多拿出来玩味几次 非常有点巧妙呢,tarjan,大概就是当前结点和它儿子结点的羁绊 WA了俩小时,,,原因是,这个题是多数据的(还没告诉你T,用scanf!=EO ...

  3. POJ 1470 Closest Common Ancestors(LCA&RMQ)

    题意比较费劲:输入看起来很麻烦.处理括号冒号的时候是用%1s就可以.还有就是注意它有根节点...Q次查询 在线st算法 /*************************************** ...

  4. POJ 1470 Closest Common Ancestors(LCA 最近公共祖先)

    其实这是一个裸求LCA的题目,我使用的是离线的Tarjan算法,但是这个题的AC对于我来说却很坎坷……首先是RE,我立马想到数组开小了,然后扩大了数组,MLE了……接着把数组调整适当大小,又交了一发, ...

  5. POJ 1470 Closest Common Ancestors LCA题解

    本题也是找LCA的题目,只是要求多次查询.一般的暴力查询就必定超时了,故此必须使用更高级的方法,这里使用Tarjan算法. 本题处理Tarjan算法,似乎输入处理也挺麻烦的. 注意: 由于查询的数据会 ...

  6. POJ 1470 Closest Common Ancestors (LCA,离线Tarjan算法)

    Closest Common Ancestors Time Limit: 2000MS   Memory Limit: 10000K Total Submissions: 13372   Accept ...

  7. poj1470 Closest Common Ancestors [ 离线LCA tarjan ]

    传送门 Closest Common Ancestors Time Limit: 2000MS   Memory Limit: 10000K Total Submissions: 14915   Ac ...

  8. POJ 1470 Closest Common Ancestors 【LCA】

    任意门:http://poj.org/problem?id=1470 Closest Common Ancestors Time Limit: 2000MS   Memory Limit: 10000 ...

  9. poj----(1470)Closest Common Ancestors(LCA)

    Closest Common Ancestors Time Limit: 2000MS   Memory Limit: 10000K Total Submissions: 15446   Accept ...

随机推荐

  1. Qt自定义类添加qvector报错

    PtsData& PtsData::operator=(const PtsData& obj){ return *this;} PtsData::~PtsData(){ }

  2. CALL 'SYSTEM' ID 'COMMAND'

    CALL 'SYSTEM' ID 'COMMAND' 语句创建 AL11文件夹 , line(), END OF tabl. DATA: lt_string TYPE STANDARD TABLE O ...

  3. delphi 根据数据库结构生成TreeView

    procedure TUIOperate.FillTree(treeview: TTreeView); var   findq: TADOQuery;   node: TTreeNode;     / ...

  4. 前端如何避免bug的产生?

    项目环境:react生态圈 界面功能基本和:增(新增一条数据).删(删除一条数据).查(展示列表).改(修改数据)挂钩. 一.展示数据列表相关[判空,控制显示距离,分页是否有效,搜索是否有效] 1.渲 ...

  5. WordPress的默认循环

    WordPress的默认循环是相对我们上一篇的WordPress自定义循环而言的,默认循环是根据链接结构的来查询数据的. 我们知道WordPress模板文件就是根据文件名来找寻模板的,这里的链接结构也 ...

  6. unity3d 触屏多点触控(旋转与缩放)

    unity3d 触屏多点触控(旋转与缩放) /*Touch OrbitProgrammed by: Randal J. Phillips (Caliber Mengsk)Original Creati ...

  7. Unity Shader基础(1):基础

    一.Shaderlab语法 1.给Shader起名字 Shader "Custom/MyShader" 这个名称会出现在材质选择使用的下拉列表里 2. Properties (属性 ...

  8. 外带IP 防火墙限制导致 IP不通

    案例: 业务报障,一台设备配了20个IP,跳板机测试都通,但从外边访问,发现部分IP通,部分不通. 排雷: 1. 从跳板机测试都通,说明所有IP 本身应该都没问题的,都可以用,2. 从其他设备测试,部 ...

  9. 剑指offer 65. 不用加减乘除做加法(Leetcode 371. Sum of Two Integers)

    剑指offer 65. 不用加减乘除做加法(Leetcode 371. Sum of Two Integers) https://leetcode.com/problems/sum-of-two-in ...

  10. C语言字符串之无重复字符的最长子串

    题目描述 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 输入: "abcabcbb" 输出: 解释: 因为无重复字符的最长子串是 . 输入: " ...