求强连通分量tarjan算法.docx
- 文档编号:8156667
- 上传时间:2023-01-29
- 格式:DOCX
- 页数:8
- 大小:185.83KB
求强连通分量tarjan算法.docx
《求强连通分量tarjan算法.docx》由会员分享,可在线阅读,更多相关《求强连通分量tarjan算法.docx(8页珍藏版)》请在冰豆网上搜索。
求强连通分量tarjan算法
Forpersonaluseonlyinstudyandresearch;notforcommercialuse
求强连通分量的tarjan算法
强连通分量:
是有向图中的概念,在一个图的子图中,任意两个点相互可达,也就是存在互通的路径,那么这个子图就是强连通分量。
(如果一个有向图的任意两个点相互可达,那么这个图就称为强连通图)。
如果u是某个强连通分量的根,那么:
(1)u不存在路径可以返回到它的祖先。
(2)u的子树也不存在路径可以返回到u的祖先。
∙例如:
∙强连通分量。
在一个非强连通图中极大的强连通子图就是该图的强连通分量。
比如图中子图{1,2,3,5}是一个强连通分量,子图{4}是一个强连通分量。
tarjan算法的基础是深度优先搜索,用两个数组low和dfn,和一个栈。
low数组是一个标记数组,记录该点所在的强连通子图所在搜索子树的根节点的dfn值,dfn数组记录搜索到该点的时间,也就是第几个搜索这个点的。
根据以下几条规则,经过搜索遍历该图和对栈的操作,我们就可以得到该有向图的强连通分量。
算法规则:
∙数组的初始化:
当首次搜索到点p时,Dfn与Low数组的值都为到该点的时间。
∙堆栈:
每搜索到一个点,将它压入栈顶。
∙当点p有与点p’相连时,如果此时(时间为dfn[p]时)p’不在栈中,p的low值为两点的low值中较小的一个。
∙当点p有与点p’相连时,如果此时(时间为dfn[p]时)p’在栈中,p的low值为p的low值和p’的dfn值中较小的一个。
∙每当搜索到一个点经过以上操作后(也就是子树已经全部遍历)的low值等于dfn值,则将它以及在它之上的元素弹出栈。
这些出栈的元素组成一个强连通分量。
∙继续搜索(或许会更换搜索的起点,因为整个有向图可能分为两个不连通的部分),直到所有点被遍历。
算法伪代码:
tarjan(u){ DFN[u]=Low[u]=++Index//为节点u设定次序编号和Low初值 Stack.push(u)//将节点u压入栈中 foreach(u,v)inE//枚举每一条边 if(!
dfn[v])//如果节点v未被访问过
{ tarjan(v)//继续向下找 Low[u]=min(Low[u],Low[v])
} elseif(vinS)//如果节点v还在栈内 Low[u]=min(Low[u],DFN[v]) if(DFN[u]==Low[u])//如果节点u是强连通分量的根
do{ v=S.pop//将v退栈,为该强连通分量中一个顶点 }while(u==v);}
演示算法流程;
从节点1开始DFS,把遍历到的节点加入栈中。
搜索到节点u=6时,DFN[6]=LOW[6],找到了一个强连通分量。
退栈到u=v为止,{6}为一个强连通分量。
返回节点5,发现DFN[5]=LOW[5],退栈后{5}为一个强连通分量。
返回节点3,继续搜索到节点4,把4加入堆栈。
发现节点4向节点1有后向边,节点1还在栈中,所以LOW[4]=1。
节点6已经出栈,(4,6)是横叉边,返回3,(3,4)为树枝边,所以LOW[3]=LOW[4]=1。
继续回到节点1,最后访问节点2。
访问边(2,4),4还在栈中,所以LOW[2]=DFN[4]=5。
返回1后,发现DFN[1]=LOW[1],把栈中节点全部取出,组成一个连通分量{1,3,4,2}。
经过该算法,求出了图中全部的三个强连通分量{1,3,4,2},{5},{6}。
可以发现,运行Tarjan算法的过程中,每个顶点都被访问了一次,且只进出了一次堆栈,每条边也只被访问了一次,所以该算法的时间复杂度为O(N+M)。
此外,该Tarjan算法与求无向图的双连通分量(割点、桥)的Tarjan算法也有着很深的联系。
学习该Tarjan算法,也有助于深入理解求双连通分量的Tarjan算法,两者可以类比、组合理解。
应用例子:
(OJ1484popularcows)
题意:
有N只牛,输入a,b的话,则说明b关注a,而且关注有传递性。
例如c关注b,且b关注a,则c也关注a。
题目问有多少只奶牛能被其他所有的奶牛关注。
把题目的模型转换:
N个顶点的有向图,有M条边。
求一共有多少个点,满足这样的条件:
所有其它的点都可以到达这个点。
这个点满足条件的充要条件是:
这个点是树中唯一的出度为0的点。
先求强连通分量,然后可以把强连通分量缩成一个点,因为,在强连通分量中的任意两个点可以到达,所有的点具有相同的性质,即它们分别能到达的点集都是相同的,能够到达它们的点集也是相同的。
然后就重新构图,缩点后的图是没有强连通分量的,否则,可将环上所有点也缩成一个点,与极大强联通分量矛盾。
所以只要找出度为0的点,并且出度为0的点只有1个,如果出度为0的点有多个的话,问题则无解。
代码:
#include
#include
#defineadj10010
#defineedg50010
structnode
{
intv;
intnext;
};
nodeedge[edg];
nodeedge1[edg];
intlow[adj],dfn[adj],Stack[adj];
intfirst[adj],first1[adj],fuck[adj];
boolins[adj];
intn,m,temp,cnt,top,count;
intcnt_size[adj],belong[adj],outdegree[adj];
voidcreat(intu,intv)
{
edge1[count].next=first1[u];
edge1[count].v=v;
first1[u]=count++;
}
voidtarjan(intu)
{
inti,v;
dfn[u]=low[u]=++temp;
Stack[top++]=u;
ins[u]=true;
for(i=first[u];i!
=-1;i=edge[i].next)
{
v=edge[i].v;
if(!
dfn[v])
{
tarjan(v);
if(low[u]>low[v])
low[u]=low[v];
}
elseif(ins[v])
{
if(low[u]>dfn[v])
low[u]=dfn[v];
}
}
if(dfn[u]==low[u])
{
intj;
do
{
top--;
j=Stack[top];
ins[j]=false;
cnt_size[cnt]++;
belong[j]=cnt;
}while(u!
=j);
cnt++;
}
}
intmain()
{
inti,j,k,v,sum,num;
inte=0;
scanf("%d%d",&n,&m);
memset(first,-1,sizeof(first));
for(k=0;k { scanf("%d%d",&i,&j); edge[e].v=j; edge[e].next=first[i]; first[i]=e; e++; } memset(dfn,0,sizeof(dfn)); memset(ins,false,sizeof(ins)); temp=cnt=top=0; memset(cnt_size,0,sizeof(cnt_size)); memset(low,0,sizeof(low)); for(i=1;i<=n;i++)求强连通分量 { if(! dfn[i]) tarjan(i); } memset(first1,-1,sizeof(first1)); count=0; for(i=1;i<=n;i++)重新构造图 { for(j=first[i];j! =-1;j=edge[j].next) { v=edge[j].v; if(belong[i]! =belong[v]) creat(belong[i],belong[v]); } } memset(outdegree,0,sizeof(outdegree)); for(i=0;i { for(j=first1[i];j! =-1;j=edge1[j].next) outdegree[i]++; } sum=num=0; for(i=0;i { if(outdegree[i]==0)求节点为0的个数 { sum=cnt_size[i]; num++; } } if(num==1) printf("%d\n",sum); else printf("0\n"); return0; } 结束! 以下无正文 仅供个人用于学习、研究;不得用于商业用途。 толькодлялюдей,которыеиспользуютсядляобучения,исследованийинедолжныиспользоватьсявкоммерческихцелях. Forpersonaluseonlyinstudyandresearch;notforcommercialuse. NurfürdenpersönlichenfürStudien,Forschung,zukommerziellenZweckenverwendetwerden. Pourl'étudeetlarechercheuniquementàdesfinspersonnelles;pasàdesfinscommerciales. Forpersonaluseonlyinstudyandresearch;notforcommercialuse
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 求强连通分量 tarjan算法 连通 分量 tarjan 算法