DFS的深入挖掘

dfs的深入挖掘应该是分为几个部分,今天学习了大概三个部分

第一:连通分量 ( 并查集也能做 )

判断一个图有几个连通分量,并且为每个点标号---说明它是属于哪一个连通分量的

那么dfs函数可以写成如下:

void dfs(int u ) {

         for ( int i = 1; i <= n; ++i ) if ( !vis[i] && map[u][i]) {

               cc[i] = count;           //count为连通分量的标号,cc【i】记录i所属的连通分量的标号

               vis[i] = true;

              dfs(i);

         }

         return;

}

第二:判断是否为二分图

和上一个dfs的代码很像,什么是二分图,之前也上一篇文章里提到了。

就是给所有的节点进行涂色,二分图有两组节点,一组我们图成1,另一组图成2(1和2分别代表一种颜色), 没有涂色的点,我们用0来标志

int  color【MAX】;

color[0] = 1;  //先给这个点着色,并且以它作为dfs的起点

bool bipa( int u ) {

          for ( int i = 0; i < n; ++i ) {

                if ( map[u][i] ) {

                         if ( color[u] == color[i] ) return false;  // 说明有两个相连的点是一个颜色的

                        if ( !color[i] ) color[i] = 3 - color[u];

                        if ( !bipa(i) ) return false;

               }

         }

        return true;

}

第三:判断割顶

这里面有一个比较关键的概念,就是时间戳。

怎么求时间戳呢?时间戳就是在按照一点顺序,一般都是标号大小的顺,对连通分量进行dfs的遍历,然后对每个结点,求出一个咋dfs中的相对的开始时间和截止时间,用pre这个数组表示开始涉及到这个点的时候,用post表示dfs在递归到这个点之后执行完毕的时间,也就是说跳出这层递归的时间,一看代码就会明白了

int pre[MAX], post[MAX];

void dfs( int u ) {

        pre[u] = level++;          //level可以被看做是相对的时间点,起始时间为0

       for ( int i = 0; i < n; ++i ) {

            if ( !vis[i] && map[u][i] ) {

                  vis[i] = true;

                  dfs(i) ;

           }

         }

        post[u] = level++;

}

根据dfs遍历节点的顺序,可以画出一棵dfs的树

对于割顶,有这样一个定理:

第一,如果是树根的话,当且仅当它有跟多的自己点

第二,如果不是树根的话,设任意节点u, 当且仅当存在u的一个子节点v,使得v节点及其所有后代都没有反向边连回u的祖先,但是可以连回u

(定理的参考文献是《算法入门经典——训练之南》)

割顶这部分今天晚上继续研究。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值