POJ - 2186 Tarjan的模板题..
来源:互联网 发布:淘宝网中老年男衬衣 编辑:程序博客网 时间:2024/06/03 18:05
暑假的时候研究过kosaraju~~A过一些强连通分量..Kosaraju需要做两个图, 一个原图一个是原图的反图(每个边的终点起点反过来..)..正着DFS一次...标记出栈顺序..再根据这个出栈顺序对反图进行一次DFS..每次能遍历到的点就是在一起的强连通分量...
Tarjan同样是用的对图DFS...Byvoid大牛的这个文章很适合初学者https://www.byvoid.com/blog/scc-tarjan
只说一些要注意的...
1、Tarjan不是一次Tarjan(1)让它搜就行了~~要循环所有的点...因为1不一定能到所有点..
2、在DFS循环边来判断时...首先是看是不是以前访问过...如果不满足再来看这个点是不是正在栈中..
3、不一定在同一强连通分量的电Low值会相等...所以弹栈时的判断条件不能是说Low相等就弹,而是说弹到一个Low = DFN 的点为止..
4、弹栈时注意instack,也就是标记点是不是在栈中的要跟着更新...
5、可能有的点完全孤立..就是根本没有边...所以做完Tarjin后..检查所有的点是不是都处理过了..如果有没处理的...直接返回没有大牛( 0 )..
这道题是要找所有人都能仰慕到的...也就是除了自己的所有强连通分量里都能到自己的强连通分量就是一个大牛集合...这里在做完Tarjan后...要先进行缩点..就是把每个强连通分量都缩成一个点..然后再来判断...
Program::
//POJ2186 找大牛 Tarjin#include<iostream>#include<math.h>#include<stack>#define MAXN 15001using namespace std;struct pp{ int x,y,next; }line[MAXN*5],line2[MAXN*5];int n,m,link[MAXN],tp[MAXN],low[MAXN],instack[MAXN],dfn[MAXN],p,numtp,sum[MAXN];bool used[MAXN];stack<int> mystack;void trajin(int h){ int i,k; low[h]=dfn[h]=++p; used[h]=instack[h]=true; mystack.push(h); k=link[h]; while (k) { if (!used[line[k].y]) { trajin(line[k].y); low[h]=min(low[h],low[line[k].y]); }else if (instack[line[k].y]) { low[h]=min(low[h],dfn[line[k].y]); //这里用low[line[k].y]来更新结果同样正确..但似乎会影响其他的找桥和割的运算 } k=line[k].next; } k=h; if (low[k]==dfn[k]) { numtp++; do { k=mystack.top(); mystack.pop(); instack[k]=true; tp[k]=numtp; }while (low[k]!=dfn[k]); } return;}void dfs(int h){ int k; used[h]=true; sum[h]++; k=link[h]; while (k) { if (!used[line2[k].y]) dfs(line2[k].y); k=line2[k].next; } return;}int getanswer(){ int i,ans,cow,k,p; p=0; numtp=0; while (!mystack.empty()) mystack.pop(); memset(used,false,sizeof(used)); for (i=1;i<=n;i++) if (!used[i]) { memset(instack,false,sizeof(instack)); trajin(i); } k=0; memset(link,0,sizeof(link)); for (i=1;i<=m;i++) if (tp[line[i].x]!=tp[line[i].y]) { k++; line2[k].x=tp[line[i].x]; line2[k].y=tp[line[i].y]; line2[k].next=link[line2[k].x]; link[line2[k].x]=k; } for (i=1;i<=n;i++) if (!tp[i]) return 0; p=n; n=numtp; memset(sum,0,sizeof(sum)); for (i=1;i<=n;i++) { memset(used,false,sizeof(used)); dfs(i); } for (i=1;i<=n;i++) if (sum[i]==n) cow=i; ans=0; for (i=1;i<=p;i++) if (tp[i]==cow) ans++; return ans;}int main(){ while (~scanf("%d%d",&n,&m)) { memset(line,0,sizeof(line)); memset(link,0,sizeof(link)); memset(tp,0,sizeof(tp)); int i; for (i=1;i<=m;i++) { scanf("%d%d",&line[i].x,&line[i].y); line[i].next=link[line[i].x]; link[line[i].x]=i; } printf("%d\n",getanswer()); } return 0; }
- POJ - 2186 Tarjan的模板题..
- POJ 2186:Popular Cows Tarjan模板题
- poj 1986tarjan模板题
- poj 1523 SPF(模板题)(Tarjan 关节点的朴素算法)
- poj 1144 Network(模板题)(Tarjan 关节点的朴素算法)
- POJ 1144 Network Tarjan 求无向图的割点的个数 Tarjan 模板题
- poj 2186 tarjan求强连通分量(模板题)
- tarjan缩点模板 poj 2186
- poj 2186 DAG+缩点+tarjan模板 (模板待消化
- poj 2186 Popular Cows(强连通分量模板题,tarjan)
- POJ 2186【Tarjan算法(模板_缩点)】
- POJ 1236 Network of Schools【tarjan算法】【模板题】
- 受欢迎的牛(Tarjan模板题)
- 裸的tarjan(模板)
- HDU1289 Tarjan-模板题
- hdu1269 tarjan模板题
- poj 2186 Tarjan (666的牛)
- poj 1144 Network (tarjan割点模板)
- 心跳包实现
- 2011中国移动开发者大会亮点之三:提交应用即享500元门票!
- 设计模式之工厂模式
- c++ 句柄样例代码(改自c++沉思录)
- Asp.net集成Windows域账户登陆
- POJ - 2186 Tarjan的模板题..
- logo字体设计心法
- iphone——使用run loop对象
- log4j.properties配置详解
- 如何检测SDK的编译版本号
- Android MediaPlayer 常用方法介绍
- IntentService实现原理及内部代码
- 怎么把数组转递给方法,并返回按从小到大排列后,返回数组!
- 【Android】调用系统应用常用uri & intent设置