POJ1144:Network(无向连通图求割点)
题目:http://poj.org/problem?id=1144
求割点。判断一个点是否是割点有两种判断情况:
如果u为割点,当且仅当满足下面的1条
1、如果u为树根,那么u必须有多于1棵子树
2、如果u不为树根,那么(u,v)为树枝边,当Low[v]>=DFN[u]时。
然后根据这两句来找割点就可以了。
模版题,就是题意看不懂。看了题解。这题算是废了,就当贴模版用吧。
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <stack> #define N 1010 using namespace std; struct node { int x,y,next; } eg[2*N]; int tt,head[N],dfn[N],low[N],n,m,ti; bool f[2*N]; void init() { tt=0; ti=1; memset(head,-1,sizeof(head)); memset(dfn,0,sizeof(dfn)); memset(f,false,sizeof(f)); } void add(int xx,int yy) { eg[tt].x=xx; eg[tt].y=yy; eg[tt].next=head[xx]; head[xx]=tt++; } void tarjan(int u,int fa) { dfn[u]=low[u]=ti++; int child=0; for(int i=head[u]; i!=-1; i=eg[i].next) { int v=eg[i].y; if(v==fa) continue; if(!dfn[v]) { child++; tarjan(v,u); low[u]=min(low[u],low[v]); if(low[v]>=dfn[u]) { f[u]=true; } } else //无向图没有横跨边 { low[u]=min(dfn[v],low[u]); } } if(fa<0&&child<2) f[u]=false; } int main() { int u,v; while(scanf("%d",&n)!=EOF&&n!=0) { init(); while(scanf("%d",&u)!=EOF&&u) { while(getchar()!='\n') { scanf("%d",&v); add(u,v); add(v,u); } } tarjan(1,-1); int sum=0; for(int i=1; i<=n; i++) { if(f[i]) sum++; } printf("%d\n",sum); } return 0; }
或者这么写
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <stack> #define N 1010 using namespace std; struct node { int x,y,next; } eg[2*N]; int tt,head[N],dfn[N],low[N],n,m,ti; bool f[2*N]; void init() { tt=0; ti=1; memset(head,-1,sizeof(head)); memset(dfn,0,sizeof(dfn)); memset(f,false,sizeof(f)); } void add(int xx,int yy) { eg[tt].x=xx; eg[tt].y=yy; eg[tt].next=head[xx]; head[xx]=tt++; } void tarjan(int u,int fa) { dfn[u]=low[u]=ti++; int child=0; for(int i=head[u]; i!=-1; i=eg[i].next) { int v=eg[i].y; if(v==fa) continue; if(!dfn[v]) { child++; tarjan(v,u); low[u]=min(low[u],low[v]); if(low[v]>=dfn[u]&&fa!=-1) { f[u]=true; } } else //无向图没有横跨边 { low[u]=min(dfn[v],low[u]); } } if(fa<0&&child>1) f[u]=true; } int main() { int u,v; while(scanf("%d",&n)!=EOF&&n!=0) { init(); while(scanf("%d",&u)!=EOF&&u) { while(getchar()!='\n') { scanf("%d",&v); add(u,v); add(v,u); } } tarjan(1,-1); int sum=0; for(int i=1; i<=n; i++) { if(f[i]) sum++; } printf("%d\n",sum); } return 0; }