求割点
模板:
void dfs(int fa, int u)
{
low[u] = dfn[u] = cnt++;
for (int i = 0; i < n; i++)
if (g[u][i] && i != fa)
{
if (dfn[i] == -1)
{
dfs(u, i);
low[u] = min(low[i], low[u]);
if (dfn[u] <= low[i])
is[u] = true;;
}
else
low[u] = min(low[u], dfn[i]);
}
}
call:
memset(dfn, -1, sizeof(dfn));
memset(is, 0, sizeof(is));
for (int i = 0; i < n; i++)
if (dfn[i] == -1)
{
dfn[i] = cnt++;
int x = 0;
for (int j = 0; j < n; j++)
if (g[i][j] && dfn[j] == -1)
{
dfs(i, j);
x++;
}
if (x > 1)
is[i] = true;
}
![ContractedBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
#define maxn 105
bool g[maxn][maxn], is[maxn];
char st[maxn * maxn];
int dfn[maxn], low[maxn];
int cnt;
int ans;
int n;
void input()
{
memset(g, 0, sizeof(g));
int a, b;
while (scanf("%d", &a), a)
{
a--;
if (getchar() != ' ')
continue;
do
{
scanf("%d", &b);
b--;
g[a][b] = true;
g[b][a] = true;
} while (getchar() == ' ');
}
}
void dfs(int fa, int u)
{
low[u] = dfn[u] = cnt++;
for (int i = 0; i < n; i++)
if (g[u][i] && i != fa)
{
if (dfn[i] == -1)
{
dfs(u, i);
low[u] = min(low[i], low[u]);
if (dfn[u] <= low[i])
is[u] = true;;
}
else
low[u] = min(low[u], dfn[i]);
}
}
int main()
{
//freopen("t.txt", "r", stdin);
while (scanf("%d", &n), n)
{
getchar();
cnt = 0;
ans = 0;
input();
memset(dfn, -1, sizeof(dfn));
memset(is, 0, sizeof(is));
for (int i = 0; i < n; i++)
if (dfn[i] == -1)
{
dfn[i] = cnt++;
int x = 0;
for (int j = 0; j < n; j++)
if (g[i][j] && dfn[j] == -1)
{
dfs(i, j);
x++;
}
if (x > 1)
is[i] = true;
}
for (int i = 0; i < n; i++)
if (is[i])
ans++;
printf("%d\n", ans);
}
return 0;
}