POJ 1144 Network (割点模板题)

题目来源:http://poj.org/problem?id=1144

除了输入处理起来比较麻烦,别的都还好。这是一道割点的模板题,题意是给出一个无向图,让你求出图中割点的个数。

使用dfs树的方法,用三个数组来实现:

vis[cur]表示节点cur当前的状态,0表示未访问,1表示在栈中,2表示已经访问过。

dfn[cur]记录点cur被访问时的深度,也就是其在这棵dfs树中的深度。

low[cur]记录点cur及其子树中可以连回的深度最小的祖先的深度。

在dfs的过程中对当前节点cur,与其相连的节点x有两种情况:

如果x没被访问过中,则递归访问节点x,并用x的low值更新cur 的low值。

如果x在栈中,说明图中存在环,即cur可连回x,则用x的深度更新cur的low值。


这样判断一个点是否为割点,分两种情况:

如果节点cur是dfs树中的根节点,那么如果cur的孩子数量大于1,则cur是割点(如果删去cur,图将不再联通,故此时cur显然是割点)。

如果cur不是根节点,那么如果low[cur]>=dfn[cur],也就时cur及其子树中所有节点能连回的深度均不比cur的要小,这样cur是割点。


代码:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int maxn=1100;
int n;
int cnt=0;
bool cut[maxn];
int head[maxn];
int vis[maxn];
int dfn[maxn];
int low[maxn];
struct data{int to,next;}e[maxn*2];
void ins(int u,int v)
{
	e[++cnt].to=v;
	e[cnt].next=head[u];
	head[u]=cnt;
}
void cut_bridge(int cur,int fa,int dep)
{
	vis[cur]=1;dfn[cur]=low[cur]=dep;
	int child=0;
	for(int i=head[cur];i;i=e[i].next)
	{
		int x=e[i].to;
		if(x!=fa&&vis[x]==1)
		{
			if(dfn[x]<low[cur])low[cur]=dfn[x];
		}
		if(vis[x]==0)
		{
			cut_bridge(x,cur,dep+1);
			child++;
			if(low[x]<low[cur])low[cur]=low[x];
			if((fa==-1&&child>1)||(fa!=-1&&low[x]>=dfn[cur]))cut[cur]=1;
		}
	}
	vis[cur]=2;
}
int main()
{
	scanf("%d",&n);
	while(n)
	{
		cnt=0;
		memset(e,0,sizeof(e));
		memset(cut,0,sizeof(cut));
		memset(head,0,sizeof(head));
		memset(vis,0,sizeof(vis));
		memset(dfn,0,sizeof(dfn));
		memset(low,0,sizeof(low));
		int u;
		scanf("%d",&u);
		while(u)
		{
			int v;
			while(getchar()!='\n')
			{
				scanf("%d",&v);
				ins(v,u);
				ins(u,v);
			}
			scanf("%d",&u);
		}
		for(int i=1;i<=n;i++)
		{
			if(!vis[i])
			{
				cut_bridge(i,-1,0);
			}
		}
		int ans=0;
		for(int i=1;i<=n;i++)if(cut[i])ans++;
		printf("%d\n",ans);
		scanf("%d",&n);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值