无向图的割点
割点:在连通图中删除割点连通图数量增加。
如何判断是不是割点:因为删除割点后连通图数量增加,所以假设这个连通图由多个连通图组成,而割点就是那个连接各小连通图的点,同时也是连接各小连通图的唯一点,所以我们就可以找的割点特性,就是这个唯一点,并以此判断是不是割点,如何判断是不是唯一点去找还有没有点与其他连通图的点相连接,所以我们引入出生时间的概念,从根节点(不固定)开始每找到一个点就标记++出生日期;这样带判断的点后面的节点出生日期理论上来说一定大于带判断的点,这是我们只要稍加处理就有了判断的条件,处理是把如果找到的点被找过来,并比该出生日期小那么更改该点出生日期为小的出生日期,并回朔,在我们判断回朔时如果发现了某点的出生日期小于判断点(每次找到根节点)那么他的子节点一定和他前面的点连接了,所以他不唯一,不是割点,反之为割点。
需要注意到是我们不要从父亲节点来在返回找父亲节点这样不太好(为什么我就不说了)...
如果有两个点那么每个点都不是割点。
///开始时我的理解有点错误,在这里感谢尚尚的更正。
代码实现在理解后就很简单了。
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #include<vector> 5 using namespace std; 6 const int maxn=1000; 7 vector<int>G[maxn]; 8 int dfs_clock;///要初始化; 9 int pre[maxn];///出生时间; 10 int low[maxn];///子节点到达的最小时间 11 int is[maxn]; 12 int dfs(int u,int fa) 13 { 14 int lowu=pre[u]++dfs_clock; 15 int kids=0; 16 for(int i=0;i<G[u].size();i++) 17 { 18 19 int v=G[u][v]; 20 21 if(pre[v]==0) 22 { 23 kids++;///如果找到新点 24 int lowv=dfs(v,u); 25 lowu=min(lowv,lowu); 26 if(lowv>=lowu){ 27 is[u]=1; 28 } 29 } 30 else if(pre[v]<lowu&&v!=fa){///找到了大于前面的点在回朔后会排除经过的点 31 lowu=pre[v]; 32 } 33 } 34 if(fa==-1&&kids==1) return is[u]=0; 35 low[u]=min(lowu,low[u]); 36 return low[u]; 37 }