zoukankan      html  css  js  c++  java
  • tarjan--割点,缩点

    统一一下代码风格

    割点

    概念:

    在无向连通图中,如果将其中一个点以及所有连接该点的边去掉,图就不再连通,那么这个点就叫做割点(cut vertex / articulation point)。

    求法:

    tarjan:判断顶点U是否为割点,用U顶点的dnf值和它的所有的孩子顶点的low值进行比较,如果存在至少一个孩子顶点V满足low[v] >= dnf[u],就说明顶点V访问顶点U的祖先顶点,必须通过顶点U,而不存在顶点V到顶点U祖先顶点的其它路径,所以顶点U就是一个割点。对于没有孩子顶点的顶点,显然不会是割点。

    code
    void tarjan(int x,int fa){
    	dfn[x]=low[x]=++cnt;
    	for (int i = head[x];i;i=ed[i].next){
    		int to=ed[i].to;
    		if (!dfn[to]){
    			tarjan(to,fa);
    			low[x]=min(low[x],low[to]);
    			if (low[to]>=dfn[x]&&x!=fa) flag[x]=1;
    			if (x==fa) child++;
    		}
    		low[x]=min(low[x],dfn[to]);
    	}
    	if (x==fa&&child>=2) flag[fa]=1; 
    }
        for (int i=1;i<=n;i++)
            if (!dfn[i]) tarjan(i,i);
        for (int i=1;i<=n;i++) if (flag[i]) ans++;
        printf("%d
    ",ans);
        for (int i=1;i<=n;i++) if (flag[i]) printf("%d ",i);
    

    缩点

    概念:

    有向图的缩点就是把有向图中强连通分量缩成一个点(道理很简单,我到了这个强连通分量的任何一点,那么这个强连通分量就能被我访问了),在处理有向图的连通性问题时有很多作用。

    求法:

    把在同一个强联通分量的点打上相同的标记,并记录不同标记的强联通分量的大小,按照题意变换就好

    code:
    void tarjan(int x){
      dfn[x]=low[x]=++cnt;
      st[++top]=x;
      for (int i = head[x];i;i=ed[i].next){
        int to=ed[i].to;
        if (!dfn[to]){
          tarjan(to);
          low[x]=min(low[x],low[to]);
        }
        else if (!col[to]) low[x]=min(low[x],dfn[to]);
      }
      if (low[x]==dfn[x]){
        ++color;
        int y;
        while (y=st[top--]){
          strong[color]++;
          col[y]=color;
          if (x==y) break;
        }
      }
    }
     for (int i = 1;i <= n;i++)
        if (!dfn[i]) tarjan(i);
    
  • 相关阅读:
    Linux命令:sed命令
    Linux命令:grep命令 | egrep命令
    Linux命令:find命令
    bash脚本编程
    Linux命令:vi | vim命令
    Linux文件权限管理
    237. 删除链表中的节点
    160. 相交链表
    538. 把二叉搜索树转换为累加树
    543.Diameter of Binary Tree
  • 原文地址:https://www.cnblogs.com/very-beginning/p/13911731.html
Copyright © 2011-2022 走看看