Beispiel #1
0
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);
    }
}
Beispiel #2
0
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);
	}
}
Beispiel #4
0
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;
}
Beispiel #5
0
Datei: F.cpp Projekt: chyyuu/ACM
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);
 }
Beispiel #8
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);
}
Beispiel #9
0
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;
}
Beispiel #10
0
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;
}
Beispiel #11
0
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];
Beispiel #12
0
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("");
}
Beispiel #13
0
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;
    }
}
Beispiel #14
0
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);
    }
}
Beispiel #15
0
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 ++;  
    }  
}  
Beispiel #17
0
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);
     }
 }
Beispiel #19
0
Datei: F.cpp Projekt: chyyuu/ACM
// 求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;
}