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\n",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);
posted @ 2020-11-01 21:24  小又又  阅读(175)  评论(0编辑  收藏  举报