图的割点

来源:互联网 发布:拼多多河鱼软件 编辑:程序博客网 时间:2024/04/30 12:41

割点的定义:如果k是割点,那么剩下的没有被访问过的点中至少会有一个点在不经过k点的情况下,无论如何再也回不到已访问过的点的~~

   要完成这项工作需要两个数组num和low,num的下标是顶点编号,存储的是时间戳(即第几个被访问到的),low的下标是顶点编号,存储的是该定点在不经过父节点时,能够回到的最小时间戳(可以就是父节点),下面来了一个高大上的公式当v是u的子节点是,如果low[v]>=num[u],那么就不能回到祖先~~

#include <stdio.h>
int a[101][101];
int flag[101];
int num[101];
int low[101];
int index;
int root;
int n;
int min(int a,int b);
void dfs(int cur,int root);
int main()
{
    int i,j,m,x,y;
    scanf("%d%d",&n,&m);
    for (i=1;i<=n;i++)
        for (j=1;i<=n;i++)
         a[i][j]=0;
   for (i=1;i<=m;i++)
    {

        scanf("%d%d",&x,&y);
        a[x][y]=1;
        a[y][x]=1;
    }
    root=1;
    index=0;
     for (i=1;i<=n;i++)
        flag[i]=0;
    dfs(1,root);
    for (i=1;i<=n;i++)
        if (flag[i]==1)
        printf("%d\n",i);
    return 0;
}
int min(int a,int b)
{

    return a<b?a:b;

}
  void dfs(int cur,int father)
  {
      int child=0,i;
      index++;
      num[cur]=index;
      low[cur]=index;
      for (i=1;i<=n;i++)
      {


        if (a[i][cur]==1)
        {
            if (num[i]==0)//如果顶点i没有被访问过,那么cur一定是i的父节点
          {
              child++;
              dfs(i,cur);
              low[cur]=min(low[cur],low[i]);
              if ((cur!=root)&&(low[i]>=num[cur]))//如果当前节点不是根节点并且符合关系式(为什么不是根节点,因为根节点就算low[i]>=num[cur]也不一定是割点,比如只有根节点1只有一个子节点2那么low[2]=1>=num[1],但是除去1节点后2节点孤立了,并不是割点(割点就是刨去取出的顶点后,剩下的顶点不能相互之间到达,取出1后,就剩本身,当然可以到达了)
                flag[cur]=1;
              if ((cur==root)&&(child==2))
              flag[cur]=1;
          }
          else //如果顶点i被访问过了
            if (i!=father)
          {

              low[cur]=min(low[cur],num[i]);
          }
        }
      }
      return;
  }





0 0