标签:
void Tarjan(u) {/*注意小写的tarjan是关键字,还有index也是*/ dfn[u]=low[u]=++index stack.push(u) for each (u, v) in E { if (v is not visted) { tarjan(v) low[u] = min(low[u], low[v]) } else if (v in stack) { low[u] = min(low[u], dfn[v]) /*这里是low[u] = min(low[u], low[v])也是可以的*/
}
} if (dfn[u] == low[u])
{ //u是一个强连通分量的根 repeat v = stack.pop
print v
until (u== v) } //退栈,把整个强连通分量都弹出来 } //复杂度是O(E+V)的
★★ 输入文件:messagew.in
输出文件:messagew.out
简单对比
时间限制:1 s 内存限制:128 MB
#include<iostream> using namespace std; #include<cstdio> #define N 100100 #include<vector> vector<int>G[N]; vector<int>ans[N]; int clac=0; bool inzhan[N]; #include<stack> #include<cstring> stack<int>s; int low[N],dfn[N]; bool flag[N]={0},ok[N]={0}; int n,m; int Index; void input() { Index=0; scanf("%d%d",&n,&m); int a,b; for(int i=1;i<=m;++i) { scanf("%d%d",&a,&b); G[a].push_back(b); } memset(inzhan,false,sizeof(inzhan)); memset(dfn,-1,sizeof(dfn)); memset(low,-1,sizeof(low)); } void Tarjan(int k) { int j; dfn[k]=low[k]=++Index;/*tarjan过程,记录到达该点的时间,和从该点出发能到达的时间最小的点*/ inzhan[k]=true;/*入栈*/ s.push(k); for(int i=0;i<G[k].size();++i) { int tp=G[k][i];/*邻接表储存,G[k][i]表示从k点出发的第i条边的终点编号*/ if(low[tp]==-1) { Tarjan(tp); low[k]=min(low[k],low[tp]); } else if(inzhan[tp]) low[k]=min(low[tp],low[k]); /*整理总共有三种情况:未被访问,访问了但是是不是强连通分量还不知道(也就是仍在栈中),访问了已经出栈了(这种不用处理,因为如果这个点在好几个强连通分量中,那么他此时一定没有出栈。因为深搜嘛)*/ } if(low[k]==dfn[k])/*low[k]==dfn[k]是这个强连通分量的标志,也就是起始位置,不能再向上找了*/ { int l; clac++;/*强连通分量个数*/ do{ l=s.top(); s.pop(); ans[clac].push_back(l); inzhan[l]=false; }while(l!=k); if(ans[clac].size()>1) flag[clac]=true;/*记录这个强连通分量中的所有点是可以传话成功的,下面在重标记每一个点*/ } } void OUT() { for(int i=1;i<=clac;++i) if(flag[i]) { for(int j=0;j<ans[i].size();++j) ok[ans[i][j]]=true; } for(int i=1;i<=n;++i) if(ok[i]) printf("T\n"); else printf("F\n"); } int main() { freopen("messagew.in","r",stdin); freopen("messagew.out","w",stdout); input(); for(int i=1;i<=n;++i) if(dfn[i]==-1) Tarjan(i); OUT(); fclose(stdin); fclose(stdout); return 0; }
标签:
原文地址:http://www.cnblogs.com/c1299401227/p/5402414.html