Cut point and cutting edge of FIG.

 

Long time no written blog and wanted to write it today or

Split point

Cut point: When you delete a point, drawing no longer Unicom, this point is called point cut (top cut)
Solution:
(1) violence
(2) DFS again get a spanning tree, if the access point to k, map k points will be divided into two
parts, one visited another part has not been visited, if k is the cut point, then, has not been visited point to
at least have one without passing k has not returned visited points. So how to determine the existence of such a
point of it v: v were once again without going through a deep search will not return to the point k previously visited, k is the cut point.
Storage method can be used adjacency matrix or adjacency list, of course, there is no difference with the adjacency matrix and basically violent, but you can feel better (following on the label affixed teacher Cheng)


#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;

int n,m,e[9][9],root;
int num[9]={0},low[9]={0},flag[9]={0},t=0;        //t用来进行时间戳的递增
void dfs(int cur,int father);	//需要传入的两个参数,当前顶点编号和父顶点的编号 

int main(void)
{
    int i,j,x,y;
    scanf("%d %d",&n,&m);
    for(i = 1;i <= n;i++)	//初始化,此处用邻接矩阵(时间复杂度为O(N*N))存储图方便演示割点算法,实际应用中一般都改为邻接表来存储(时间复杂度为O(N+M)) 
    	for(j = 1;j <= n;j++)
    		e[i][j]=0;
    		
    for(i = 1;i <= m;i++)   //输入无向图的每条边 
    {
    	scanf("%d %d",&x,&y);
    	e[x][y] = 1;
    	e[y][x] = 1;
    }
    root=1;
  	dfs(1,root);	//从1号顶点开始进行深度优先遍历
	  
	for(i = 1;i <= n;i++)  //输出割点 
		if(flag[i] == 1)
			printf("\n%d ",i); 
       
    return 0;
}

//割点算法的核心,需要传入的两个参数,当前顶点编号和父顶点的编号		
void dfs(int cur,int father)
{
	int child = 0,i,j;	//child用来记录生成树中当前顶点cur的儿子个数
	
	t++;	//时间戳加1
	num[cur] = t;	//当前顶点cur的时间戳
	low[cur] = t;	//当前顶点cur能够访问到最早顶点的时间戳,刚开始就是自己
	for(i = 1;i <= n;i++)	//枚举与当前顶点cur有边相连的顶点i 
	{
		if(e[cur][i] == 1)
		{
			if(num[i] == 0)	//如果顶点i的时间戳为0,说明顶点i还没有被访问过
			{
				child++;
				//继续往下深度优先遍历 
				dfs(i,cur); //从生成树的角度来说,此时的i为cur的儿子
				//更新当前顶点cur能访问到最早顶点的时间戳
				low[cur] = min(low[cur],low[i]);
				//如果当前顶点不是根结点并且满足low[i]>=num[cur],则当前顶点为割点
				if(cur != root && low[i] >= num[cur])
					flag[cur] = 1;
				//如果当前顶点是根结点,在生成树中根结点必须要有两个儿子,那么这个根节点才是割点
				if(cur == root && child == 2)
					flag[cur] = 1; 
			}
			else if(i != father)  //否则如果顶点i曾经被访问过,并且这个顶点不是当前顶点cur的父亲,
			{                   //则说明此时的i为cur的祖先,因此需要更新当前顶点cur能访问到最早顶点的时间戳 
				low[cur] = min(low[cur],num[i]);			
			} 
		} 
	}
	return;
}

Adjacency table with a little difficulty there is no change on the line

#include <cstdio> 
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#define maxn 100010
//#define will
using namespace std;

int first[2*maxn],next[2*maxn],cnt;
int n,m,u[2*maxn],v[2*maxn],t;
int root = 1,flag[maxn],num[maxn],low[maxn];
void dfs(int cur,int father)
{
	int child = 0;
	t++;
	num[cur] = t;
	low[cur] = t;
	for(int i = first[cur];i != -1;i = next[i])
	{
		if(num[v[i]] == 0)
		{
			child++;
			dfs(v[i],cur);
			low[cur] = min(low[cur],low[v[i]]);
			if(cur != root && low[v[i]] >= num[cur])
				flag[cur] = 1;
			if(cur == root && child == 2)
				flag[cur] = 1;
		}
		else if(v[i] != father)
			low[cur] = min(low[cur],num[v[i]]);
	}
	return;
}
int main()
{
	#ifdef will
	freopen("test.in","r",stdin);
	freopen("test.out","w",stdout);
	#endif
	
	scanf("%d%d",&n,&m);
	memset(first,-1,sizeof(first));
	memset(next,-1,sizeof(next));
	for(int i = 1;i <= m;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		//邻接表 
		u[++cnt] = x,v[cnt] = y;
		next[cnt] = first[u[cnt]];
		first[u[cnt]] = cnt;
		u[++cnt] = y,v[cnt] = x;
		next[cnt] = first[u[cnt]];
		first[u[cnt]] = cnt;
	}
	dfs(1,1);
	for(int i = 1;i <= n;i++)
		if(flag[i] == 1)
			printf("%d\n",i);
			
	#ifdef will
	fclose(stdin);
	fclose(stdout);
	#endif
	return 0;
}

It seems like this would bug? ? Anyway, this too can not afford Road template question , it should still be slightly changed line (but I do not want changed)

Cutting edge

In fact, cutting edge and cut point is a reason just need to if(cur != root && low[v[i]] >= num[cur])change if(cur != root && low[v[i]] > num[cur])
the following paste the code (as if there are still big bug bug)

#include <cstdio> 
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#define maxn 500010
//#define will
using namespace std;

int first[2*maxn],next[2*maxn],cnt;
int n,m,u[2*maxn],v[2*maxn],index,tot;
int root = 1,flag[maxn],num[maxn],low[maxn];
struct node
{
	int x;
	int y;
}ans[2*maxn];
bool cmp(node tx,node ty)
{
	if(tx.x == ty .x)
		return tx.y < ty.y;
	return tx.x < ty.x;
}
void dfs(int cur,int father)
{
//	int child = 0;
	index++;
	num[cur] = index;
	low[cur] = index;
	for(int i = first[cur];i != -1;i = next[i])
	{
		if(num[v[i]] == 0)
		{
//			child++;
			dfs(v[i],cur);
			low[cur] = min(low[cur],low[v[i]]);
			if(cur != root && low[v[i]] >= num[cur])
				ans[++tot].x = cur,ans[tot].y = v[i];
//				printf("%d-%d\n",cur,v[i]);
		}
		else if(v[i] != father)
			low[cur] = min(low[cur],num[v[i]]);
	}
	return;
}
int main()
{
	#ifdef will
	freopen("blocking.in","r",stdin);
	freopen("blocking.out","w",stdout);
	#endif
	
	scanf("%d%d",&n,&m);
	memset(first,-1,sizeof(first));
	memset(next,-1,sizeof(next));
	for(int i = 1;i <= m;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		//邻接表 
		u[++cnt] = x,v[cnt] = y;
		next[cnt] = first[u[cnt]];
		first[u[cnt]] = cnt;
		u[++cnt] = y,v[cnt] = x;
		next[cnt] = first[u[cnt]];
		first[u[cnt]] = cnt;
	}
	dfs(1,1);
	sort(ans+1,ans+1+tot,cmp);
	for(int i = 1;i <= tot;i++)
		printf("%d-%d\n",ans[i].x,ans[i].y);
	
	#ifdef will
	fclose(stdin);
	fclose(stdout);
	#endif
	return 0;
}

Guess you like

Origin www.cnblogs.com/wknclizu/p/11068398.html