题意:
给你一张图,定义critical点:去掉该点,会出现两个点不能互相达到,求图中critical点的个数
分析:
割点:
在一个无向图中,如果删掉点
后图的连通块数量增加,则称点
为图的割点。
对于搜索树上的非根结点
,如果存在子节点
满足
,即
向上无法达到
的祖先,则
为割点。
对于搜索树上的根节点
,若它的子节点数
,则
为割点
critical点符合割点的定义,通过Tarjan算法求出割点即可
代码:
#include <iostream>
#include <sstream>
#include <cstring>
using namespace std;
const int MAXN = 1e4+14;
int head[MAXN],dfn[MAXN],low[MAXN],vis[MAXN];
int n,cnt;
string s;
struct edge{
int to,nxt;
}e[MAXN];
void add(int u,int v)
{
e[++cnt].to = v;
e[cnt].nxt = head[u];
head[u] = cnt;
}
void Tarjan(int u,int fa)
{
dfn[u] = low[u] = ++cnt;
int son = 0;
for(int i = head[u]; i ;i = e[i].nxt){
int v = e[i].to;
if(v == fa) continue;
if(!dfn[v]){
son++; //这句放在外面也不影响结果
Tarjan(v,u);
low[u] = min(low[u],low[v]);
if(u == fa && son >= 2) vis[u] = 1;
else if(u != fa && low[v] >= dfn[u]) vis[u] = 1;
}
else low[u] = min(low[u],dfn[v]);
}
}
void init()
{
cnt = 0;
memset(head,0,sizeof(head));
memset(dfn,0,sizeof(dfn));
memset(vis,0,sizeof(vis));
}
int main()
{
while(cin>>n && n)
{
init();
getline(cin,s); //处理掉换行符
while(getline(cin,s) && s[0] != '0')
{
int u,v;
stringstream input;
input << s;
input >> u;
while(input >> v){
add(u,v);
add(v,u);
}
}
for(int i = 1;i <= n; ++i){
if(!dfn[i]) Tarjan(i,i);
}
int res = 0;
for(int i = 1;i <= n; ++i) if(vis[i]) res++;
cout<<res<<endl;
}
return 0;
}