POJ 1144 Network (割点模板题)

来源:互联网 发布:如何做好淘宝客服工作 编辑:程序博客网 时间:2024/06/05 07:33

题目来源: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;}


原创粉丝点击