[笔记]: Tarjan算法求有向图的强连通分量
来源:互联网 发布:apache实现负载均衡 编辑:程序博客网 时间:2024/05/18 18:01
所谓Tarjan算法建议学习算法竞赛入门经典训练指南中的这一章对此的介绍
因为我的解释需要中文十级才看的懂
核心就是dfs中记录一个二元组
一个叫dfn(就是算法训练入门经典中的pre)还有一个叫low
dfn就是在图中dfs时的时间戳
low则是这个点能访问回到的点的dfn的最小值
举个例子
例如
1->4<->5
此时的1 4 5 dfn值分别为123
当访问到5的时候low值都初始化为自己的dfn本身(自己可以到达自己)
因为此时5没有连别的点 dfn(5)会又搜索到4 所以此时的low[5]=min[low[5],dfn[4]]=2(原来是3)
然而4搜不到1 那么4的low值就还是dfn(4) 此时4 5是一个强连通分量
Tarjan算法中需要用一个栈 记录搜到的点 用一个instack标记每个点是否在栈中
还是上面的例子 当搜到5的时候栈里面是 1 4 5
当5 反向到4的时候 如果4 在栈中 就说明4可以搜索到5(核心)
因为5可以到4且4可以到5 那么此时4 5就是强连通分量 把4 5弹出 连通分量的数目加一
例题就是poj的2186
===传送门===
求出受欢迎的牛的个数
其实就是求某个出度为0的连通的元素的个数
先套模板Tarjan求强联通分量
求这个个数时 如果某个点连到了别的连通分量 那么这个点所在的连通分量都不是受欢迎的(这个连通分量的牛认为别人联通分量的牛受欢迎 那么这个组就不收欢迎了)
注意!!(WA了刚好10次。。血的教训)
1.根据题意这个出度为0的连通分量最多只有一个如果大于1个 则直接输出0
2.还有就是此题是多组输入数据。。。。(调了一个晚上)
下面代码 虽然因为后面调试开了好多好多数组 改的不成样子了
但是Tarjan模板还是可以将就着看的
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<cmath>using namespace std;int Stack[100005],top,num,ans=0,cnt=0,dfn[100005],low[10005],head[10005],id[10005];int answer=0;bool inStack[10005],failed[10005];struct node{int to,next;}e[100005];void insert(int x,int y){e[++cnt].to=y;e[cnt].next=head[x];head[x]=cnt;}void tarjan(int x){num++;Stack[++top]=x;inStack[x]=1;dfn[x]=num;low[x]=num;for(int i=head[x];i;i=e[i].next){int k=e[i].to;if(!dfn[k]){tarjan(k);low[x]=min(low[x],low[k]);}else{ if(inStack[k])low[x]=min(low[x],dfn[k]);}}if(low[x]==dfn[x]){int t=Stack[top];ans++;while(t!=x){ inStack[t]=0;id[t]=ans; t=Stack[--top];}id[x]=ans;top--;}}int main(){int n,m;while(scanf("%d%d",&n,&m)!=EOF) {memset(head,0,sizeof(head));memset(Stack,0,sizeof(Stack));memset(failed,0,sizeof(failed));memset(inStack,0,sizeof(inStack));memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low));memset(id,0,sizeof(id));top=0;num=0;cnt=0;ans=0;answer=0;int x,y;for(int i=1;i<=m;i++){scanf("%d%d",&x,&y);insert(x,y);}for(int i=1;i<=n;i++){if(!dfn[i])tarjan(i);}for(int i=1;i<=n;i++){for(int j=head[i];j;j=e[j].next){int k=e[j].to;if(id[k]!=id[i]){failed[id[i]]=1;}}}int tmp=0;for(int i=1;i<=ans;i++){if(!failed[i]) tmp++;}if(tmp>1){puts("0");continue; }for(int i=1;i<=n;i++){if(!failed[id[i]]) answer++;}printf("%d\n",answer);}return 0;}
- [笔记]: Tarjan算法求有向图的强连通分量
- 求有向图的强连通分量 Tarjan算法学习笔记
- Tarjan 算法 求有向图强连通分量
- Tarjan求有向图的强连通分量(Tarjan算法描述)
- Tarjan求有向图的强连通分量(Tarjan算法描述)
- Tarjan求有向图的强连通分量(Tarjan算法描述)
- 有向图强连通分量tarjan算法学习笔记
- Tarjan求有向图的强连通分量
- ccf+tarjan+求有向图的强连通分量
- 求有向图的强连通分量<Tarjan>
- 有向图的强连通分量的Tarjan算法
- 有向图强连通分量的Tarjan算法
- 有向图强连通分量的Tarjan算法
- 【转载】有向图强连通分量的Tarjan算法
- 有向图强连通分量的Tarjan算法[ZZ]
- 有向图强连通分量的Tarjan算法
- 有向图强连通分量的Tarjan算法
- 有向图强连通分量的Tarjan算法
- 电商行业一览表
- 台湾李宏毅ML2016-hw0
- filezillal连接出现“ECONNREFUSED
- 页面多列布局
- ubuntu系统查看有线/无线MAC地址
- [笔记]: Tarjan算法求有向图的强连通分量
- TCP通信过程(一)
- LocalBroadcastManager 的使用和源码分析
- Hibernate中Inverse和cascade的区别
- 04_BootScrap——CRUD(动态页面上篇)
- 《珠珠图案》创意——发挥聪明才智,灵活应用软件,创造性扩展。
- 人脸识别趟坑历程
- Android listview 右滑删除
- A simple java application.