形成割点的条件:
如果u为割点,当且仅当满足下面的1/2
1、如果u为树根,那么u必须有多于1棵子树
2、如果u不为树根,那么(u,v)为树枝边,当Low[v]>=DFN[u]时。
题目直接套tarjan模版求割点个数
#include<cstring>
#include<string>
#include<iostream>
#include<queue>
#include<cstdio>
#include<algorithm>
#include<map>
#include<cstdlib>
#include<cmath>
#include<vector>
//#pragma comment(linker, "/STACK:1024000000,1024000000");
using namespace std;
#define INF 0x3f3f3f3f
#define maxn 200004
int fir[maxn],nex[maxn],v[maxn],e_max;
int sta[maxn],dfn[maxn],low[maxn],ans[205][205];
int lay;
bool cut[maxn];
void init()
{
memset(fir,-1,sizeof fir);
e_max=0;
}
void add_edge(int s,int t)
{
int e=e_max++;
v[e]=t;
nex[e]=fir[s];
fir[s]=e;
}
void tarjandfs(int k,int pre)
{
dfn[k]=++lay;
low[k]=lay;
int son=0;
for(int i=fir[k]; ~i; i=nex[i])
{
int e=v[i];
if(e==pre) continue ;
if(!dfn[e])
{
son++;
tarjandfs(e,k);
if(low[k]>low[e]) low[k]=low[e];
if(k!=pre&&low[e]>=dfn[k])
{
cut[k]=true;
}
}
else if(low[k]>dfn[e]) low[k]=dfn[e];
}
if(k==pre&&son>1) cut[k]=true;
}
int tarjan(int n)
{
lay=0;
memset(cut,false,sizeof cut);
memset(dfn,0,sizeof dfn);
for(int i=1; i<=n; i++)
{
if(!dfn[i]) tarjandfs(i,i);
}
int num=0;
for(int i=1; i<=n; i++)
{
if(cut[i]) num++;
}
return num;
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF&&n)
{
init();
getchar();
char s[505];
while(gets(s)!=NULL)
{
if(strcmp(s,"0")==0) break;
int now=0,temp=0,flag=0;
int len=strlen(s);
s[len++]=' ';
for(int i=0; i<len; i++)
{
if(s[i]>='0'&&s[i]<='9')
{
if(!flag) now=now*10+(s[i]-'0');
else temp=temp*10+(s[i]-'0');
}
else
{
if(!flag) flag=1;
else add_edge(now,temp),add_edge(temp,now),temp=0;
}
}
}
int ans=tarjan(n);
printf("%d\n",ans);
}
return 0;
}