无向图求割点,开始看题后不知道求什么,看了discussi才知道是求割点,然后就在网上找了找关于割点的知识。然后在http://blog.csdn.net/xinghongduo/article/details/6202646 这个大神的博客里看见关于割点知识和一些证明。
割点就是在一个图中,如果去掉某个顶点,及与它相关联的边后,这个图的联通分量增加了,那么这个点就是一个割点。
用dfn[v]来记录DFS遍历的深度,low[v]来记录v能遍历的最浅深度,然后对于点v来说:
1,如果v是根节点,并且它的子女数大于以及等于2个,那个v是割点;
割点就是在一个图中,如果去掉某个顶点,及与它相关联的边后,这个图的联通分量增加了,那么这个点就是一个割点。
用dfn[v]来记录DFS遍历的深度,low[v]来记录v能遍历的最浅深度,然后对于点v来说:
1,如果v是根节点,并且它的子女数大于以及等于2个,那个v是割点;
2,如果v不是根节点,并且存在它的一个子女u,如果low[u]>=dfn[v],那么v是割点。
#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<queue>
#include<stack>
#include<vector>
using namespace std;
const int inf=0x7ffffff;
const double PI=acos(-1.0);
const double eps=1e-8;
bool map[110][110];
int dfn[110];
int low[110];
int ans[110];
bool vis[110];
int deepth,root,n;
void dfs(int f)
{
dfn[f]=deepth;
low[f]=deepth++;
vis[f]=true;
for(int i=1;i<=n;i++)
{
if(map[f][i])
{
if(!vis[i])
{
dfs(i);
low[f]=min(low[f],low[i]);
if(low[i]>=dfn[f] && f!=1)
ans[f]++;
else if(f==1) root++;
}
else low[f]=min(low[f],dfn[i]);
}
}
}
void init()
{
memset(map,false,sizeof(map));
memset(vis,false,sizeof(vis));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(ans,0,sizeof(ans));
}
int main()
{
int m,a;
char c;
while(~scanf("%d",&n),n)
{
init();
while(1)
{
scanf("%d",&m);
if(m==0)
break;
while(getchar()!='\n')
{
scanf("%d",&a);
map[m][a]=map[a][m]=1;
}
}
deepth=1;
root=0;
dfs(1);
int cnt=0;
if(root>=2)
cnt++;
for(int i=2;i<=n;i++)
if(ans[i])
cnt++;
printf("%d\n",cnt);
}
return 0;
}