Tarjan求割点

题目:

给定一个N个顶点的无向图,顶点从1到N编号,求此无向图割点数。

(当你去掉其中一个点时,形成两个及以上的连通分量,此点即是割点)

输入

第一行包含一个整数N (1 \le N \le 100)N (1N100)。

接下来若干行,每行有若干整数a, b, c, d, ...a,b,c,d,...,表示aa 与 b, c, d, ...b,c,d,... 之间分别有一条无向边相连。

如果a = 0a=0则表示输入结束。

 

输入保证是一个连通图。

输出

输出割点的数目。

样例

输入

5
5 1 2 3 4
0

输出

1

输入

6
2 1 3
5 4 6 2
0

输出

2
/*************************************************************************
  > Author: Henry Chen
  > Mail: 390989083@qq.com 
************************************************************************/
#include<bits/stdc++.h>
using namespace std;
const int maxn = 101;
int tt;
vector <int> vec[maxn];
int pre[maxn];
int low[maxn];
int ck[maxn];
int dfs(int u,int fa)
{
    int lu = pre[u] = ++tt;
    int sm = 0;
    for(int i = 0;i < vec[u].size();i++)
    {
        int v = vec[u][i];
        if(!pre[v])
        {
            sm++;
            int lv = dfs(v,u);
            lu = min(lu,lv);
            if(lv >= pre[u])
            {
                ck[u] = 1;
            }
        }
        else if(pre[v] < pre[u]&&v != fa)
        {
            lu = min(lu,pre[v]);
        }
    }
    if(fa < 0&&sm == 1)
    {
        ck[u] = 0;
    }
    return low[u] = lu;
}
int get(char *s)
{
    int v=0;
    for(int i = 0;s[i];i++)
    {
        v = v*10 + s[i] - '0';
    }
    return v;
}
int main()
{
    int n,m;
    cin >> n;
    tt = 0;
    memset(pre,0,sizeof(pre));
    memset(ck,0,sizeof(ck));
    char str[10];
    while(scanf("%s",str) == 1)
    {
        if(str[0] == '0') 
        {
            break;
        }
        int u = get(str);
        while(scanf("%s",str)==1)
        {
            int v = get(str);
            vec[u].push_back(v);
            vec[v].push_back(u);
            if(getchar() == '\n') 
            {
                break;
            }
        }
    }
    dfs(1,-1);
    int ans = 0;
    for(int i = 1;i <= n;i++)
    {
        if(ck[i])
        {
            ans++;
        }
    }
    printf("%d\n",ans);
    return 0;
}

 

posted @ 2020-09-03 23:56  秘之洋洋  阅读(161)  评论(0编辑  收藏  举报