void Tarjan(int u) { int i,v; dfn[u]=low[u]=++cnt; stack[++top]=u; vis[u]=1; for (i=head[u];i!=-1;i=e[i].next) { v=e[i].v; if (!dfn[v]) { Tarjan(v); if (low[v]<low[u]) low[u]=low[v]; } else if (vis[v] && dfn[v]<low[u]) low[u]=dfn[v]; } if (dfn[u]==low[u]) { scc++; do { v=stack[top--]; vis[v]=0; id[v]=scc; } while(v!=u); } }
void Tarjan(int u) { DFN[u]=LOW[u]=++TimeS; Stack[++St]=u; inS[u]=1; for (int p=G.Head[u]; p; p=G.Pre[p]) { if (!DFN[G.V[p]]) { Tarjan(G.V[p]); if (LOW[G.V[p]]<LOW[u]) LOW[u]=LOW[G.V[p]]; } else if (inS[G.V[p]]) { if (DFN[G.V[p]]<LOW[u]) LOW[u]=DFN[G.V[p]]; } } if (DFN[u]==LOW[u]) { int v; ++SCCt; do { v=Stack[St--]; inS[v]=0; SCC[v]=SCCt; } while (u!=v); } }
void Tarjan(int node) { dfn[node]=low[node]=index++; stack[top++]=node; instack[node]=1; for(int i=first[node];i!=-1;i=arc[i].next) { if(!dfn[arc[i].y]) { Tarjan(arc[i].y); low[node]=Min(low[node],low[arc[i].y]); } else if(instack[arc[i].y]) { low[node]=Min(low[node],dfn[arc[i].y]); } } if(dfn[node]==low[node]) //当DFN(u)=Low(u)时,以u为根的搜索子树上所有节点是一个强连通分量。 { scc++; do { instack[stack[top-1]]=0; belong[stack[top-1]]=scc; top--; }while(stack[top]!=node); } }
int main() { Index = cnt = stop = 0; memset(IN,0,sizeof(IN)); memset(DFN,0,sizeof(DFN)); for (i=1; i<=n*2; i++) if (!DFN[i]) Tarjan(i); return 0; }
void Solve() { memset(num,0,sizeof(num)); memset(DFN,0,sizeof(DFN)); memset(Instack,false,sizeof(Instack)); memset(Low,0,sizeof(Low)); Index=scc=top=0; for(int i=1; i<=N; i++) { //缩点 if(!DFN[i]) Tarjan(i); } }
int main() { Graph initial, reduced; initial = buildGraph(); Tarjan(initial); reduced = reduceGraph(initial, translation); printSccGraph(reduced, n_scc); freeGraph(reduced); freeTarjan(); return 0; }
void BCC() { size = 0; while (!S.empty()) S.pop(); memset(id, -1, sizeof(id)); for (int i = 0; i < N; i++) dfn[i] = -1; for (int i = 0; i < N; i++) if (dfn[i] == -1) Tarjan(i, 0); }
void getCUTP(int n) { sort(remE,remE+Ecou); for(int i=1; i<Ecou; ++i) if(remE[i]==remE[i-1]) chongE[remE[i].num]=chongE[remE[i-1].num]=1; for(int i=1; i<=n; ++i) if(!DFN[i]) Tarjan(i,i); }
bool solvable(int n) { //n是总个数,需要选择一半 memset(DFN, 0, sizeof(DFN)); memset(Instack, false, sizeof(Instack)); memset(num, 0, sizeof(num)); Index = scc = top = 0; for (int i = 0; i < n; i++) { if (!DFN[i]) { Tarjan(i); } } for (int i = 0; i < n; i += 2) { if (Belong[i] == Belong[i ^ 1]) { return false; } } return true; }
int TwoSAT(int n) { int i,head,tail,u,v; cnt=scc=top=0; memset(dfn,0,sizeof(dfn)); for (i=1;i<=2*n;i++) if (!dfn[i]) Tarjan(i); for (i=1;i<=n;i++) { if (id[i]==id[i+n]) return 0; //一组内两点在同一连通分量中,无解 cf[id[i]]=id[i+n]; cf[id[i+n]]=id[i]; //在缩点的图中标记互斥的缩点 } memset(indeg,0,sizeof(indeg)); memset(col,0,sizeof(col)); InitEdge2(); for (i=0;i<index;i++) //缩点后重新按原来的边来建图 { u=e[i].u; v=e[i].v; if (id[u]!=id[v]) { AddEdge2(id[v],id[u]); //反向,是因为u->v,如果选择了u必须选择v,则应反向 indeg[id[u]]++; //统计入度 } } head=1,tail=1; for (i=1;i<=scc;i++) if (indeg[i]==0) que[tail++]=i; //入度为0入队列 while (head<tail) { u=que[head]; head++; if (col[u]==0) //未着色的点x染成1,同时将与x矛盾的点cf[x]染成2 { col[u]=1; col[cf[u]]=2; } for (i=head2[u];i!=-1;i=e2[i].next) { v=e2[i].v; if (--indeg[v]==0) que[tail++]=v; //入度为0入队列 } } memset(ans,0,sizeof(ans)); for (i=1;i<=n;i++) if (col[id[i]]==1) ans[i]=1; return 1; }
void Tarjan(int u) { int v,i; dfn[u]=low[u]=++cnt;//开始时dfn[u]==low[u] stack[top++]=u; //当前点进栈 vis[u]=1; for (i=head[u];i!=-1;i=Edge[i].next) { v=Edge[i].v; if (dfn[v]==0) //如果v点还未遍历 { Tarjan(v); //向下遍历 low[u]=min(low[u],low[v]) //确保low[u]最小 } else if (vis[v] && low[u]>dfn[v]) low[u] = dfn[v];
void Main() { G.Init(); scanf("%d%d",&N,&M); for (int i=1; i<=M; ++i) { int a,b; scanf("%d%d",&a,&b); G.AddEdge(a,b); } SCCt=0; St=0; memset(DFN,0,sizeof(DFN)); memset(LOW,0,sizeof(LOW)); for (int i=0; i<N; ++i) if (!DFN[i]) Tarjan(i); memset(Rd,0,sizeof(Rd)); for (int u=0; u<N; ++u) { for (int p=G.Head[u]; p; p=G.Pre[p]) { if (SCC[G.V[p]]!=SCC[u]) { Rd[SCC[G.V[p]]]++; } } } int Rd0Count=0,point; for (int i=1; i<=SCCt; ++i) { if (Rd[i]==0) { Rd0Count++; point=i; } } if (Rd0Count>1) { puts("Confused\n"); return ; } for (int i=0; i<N; ++i) { if (SCC[i]==point) printf("%d\n",i); } puts(""); }
void Tarjan(int u,int pre) { int v; int couSon=0; LOW[u]=DFN[u]=++Index; for(int i=head[u]; i!=-1; i=E[i].next) { v=E[i].to; if(v==pre) // !!! continue; if(!DFN[v]) { ++couSon; Tarjan(v,u); if(LOW[v]<LOW[u]) LOW[u]=LOW[v]; if(DFN[u]<LOW[v] && !chongE[i]) { bridge[i]=1; bridge[i^1]=1; // ++couBridge; } if(u!=pre && DFN[u]<=LOW[v]) { cutp[u]=1; ++add_block[u]; } } else if(DFN[v]<LOW[u]) LOW[u]=DFN[v]; } if(u==pre && couSon>1) { cutp[u]=1; add_block[u]=couSon-1; } }
void Tarjan(int i) { int j; DFN[i] = Low[i] = ++Index; S[++stop] = i; IN[i] = true; for (edge *e=v[i]; e; e=e->nx) if (!DFN[(j = e->j )]) { Tarjan(j); if (Low[j] < Low[i]) Low[i] = Low[j]; } else if (IN[j] && DFN[j] < Low[i]) Low[i] = DFN[j]; if (Low[i] == DFN[i]) { size[++cnt] = 0; do { size[cnt]++; bel[S[stop]] = cnt; IN[S[stop--]] = false; } while (S[stop+1]!=i); } }
void Tarjan(int u, int pre) { vis[u] = 1; FOREACH(e, lst[u]) if (vis[(*e).first]) //计算出LCA lca[Find((*e).first)].push_back((*e).second); for (int i = ent[u], v; ~i; i = nxt[i]) if ((v = ver[i]) != pre) { Tarjan(v, u); par[v] = u; } FOREACH(e, lca[u]) { int i = (*e); int x = qry[i].first, y = qry[i].second; Find(x); Find(y); //计算第i个query的dp值 res[i] = max(Max[y] - Min[x], max(up[x], dn[y])); }
void Tarjan(int u, int fa) { dfn[u] = low[u] = dfsNum ++; vis[u] = 1; stack[top++] = u; int flag = 0; for(int i = head[u]; i != -1; i = e[i].next) { int v = e[i].v; if(v == fa && !flag) { flag = 1; continue; } if(!vis[v]) { Tarjan(v, u); low[u] = min(low[u], low[v]); } else if(col[v] == -1) low[u] = min(low[u], dfn[v]); if(dfn[u] < low[v]) brige.pb(make_pair(u, v)); } // 压栈取点构建连通分量 if(low[u] == dfn[u]) { while(stack[top-1] != u) col[stack[--top]] = bch, sum[bch] += a[stack[top]]; top --; sum[bch] += a[stack[top]]; col[u] = bch ++; } }
void Tarjan(int u) { int v; Low[u] = DFN[u] = ++Index; Stack[top++] = u; Instack[u] = true; for (int i = head[u]; i != -1; i = edge[i].next) { v = edge[i].to; if (!DFN[v]) { Tarjan(v); if (Low[u] > Low[v]) { Low[u] = Low[v]; } } else if (Instack[v] && Low[u] > DFN[v]) { Low[u] = DFN[v]; } } if (Low[u] == DFN[u]) { scc++; do { v = Stack[--top]; Instack[v] = false; Belong[v] = scc; num[scc]++; } while (v != u); } }
void Tarjan(int u, int dep) { dfn[u] = low[u] = dep; S.push(u); for (int i = 0; i < graph[u].size(); i++) { int v = graph[u][i].first; int id = graph[u][i].second; if (dfn[v] == -1) { visit[id] = true;//It's an undirected graph Tarjan(v, dep + 1); low[u] = min(low[u], low[v]); } else if (!visit[id]) { low[u] = min(low[u], dfn[v]); } } if (low[u] == dfn[u]) { int v; size++; do { v = S.top(); S.pop(); id[v] = size; } while (u != v); } }
// 求u 出发可以找到的联通分支。 void Tarjan(int u) { int i,v; Low[u]=DFN[u]=++Index; Stack[++top]=u; Instack[u]=true; for(i=head[u]; i!=-1; i=E[i].next) { v=E[i].to; if(!DFN[v]) { // 没有形成环,继续深搜 Tarjan(v); if(Low[u]>Low[v]){ //如果 u 大于 v, 说明 v 的某个儿子可以到达v的一个祖先,且这个祖先也是 u 的祖先。 //那么把 u 的标记为那个临时祖先。 Low[u]=Low[v]; } } else if(Instack[v] && Low[u]>DFN[v]) { // 找到一个环, v 是 u 的一个祖先 // u 的 临时祖先标记为 v. Low[u]=DFN[v]; } } if(Low[u]==DFN[u]) { //能够到达这里,说明 u 是一个祖先了。 //而且 Stack 中 u 之后的都是 u 的儿子,且可以互相到达。 scc++; do { v=Stack[top--]; Instack[v]=false; Belong[v]=scc; num[scc]++; } while(u!=v); } return; }