无向图求割点 UVA 315

***割点概念:去掉一个点后图不连通,该点就为割点

割点满足的条件:

一个顶点u是割点,当且仅当满足(1)或(2)

(1) u为树根,且u有多于一个子树。

(2) u不为树根,且满足存在(u,v)为树枝边(或称 父子边,即u为v在搜索树中的父亲),使得 dfn(u)<=low(v)。

题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=122091#problem/B***

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
#define N 100005

int n;
int dfn[N], low[N], Father[N];
int Time;

vector<vector<int> > G;

void Init()
{
    G.clear();
    G.resize(n+5);
    memset(dfn, 0, sizeof(dfn));
    memset(low, 0, sizeof(low));
    memset(Father, 0, sizeof(Father));
    Time=0;
}

void Tarjan(int u, int fa)
{
    dfn[u]=low[u]=++Time;
    Father[u]=fa;
    int len=G[u].size(), v;

    for(int i=0; i<len; i++)
    {
        v=G[u][i];
        if(!dfn[v])
        {
            Tarjan(v, u);
            low[u]=min(low[u], low[v]);
        }
        else if(fa!=v)
            low[u]=min(low[u], dfn[v]);
    }
}

void solve()
{
    int RootSon=0, ans=0, v;
    bool Cut[N]= {false};

    for(int i=1; i<=n; i++)
    {
        if(!low[i])
            Tarjan(i, 0);
    }

    for(int i=2; i<=n; i++)
    {
        v=Father[i];
        if(v==1)
            RootSon++;
        else if(dfn[v]<=low[i])
            Cut[v]=true;
    }
    for(int i=2; i<=n; i++)
    {
        if(Cut[i])
            ans++;
    }
    if(RootSon>1)
        ans++;
    printf("%d\n", ans);
}

int main()
{
    while(scanf("%d", &n), n)
    {
        Init();
        int a, b;
        char ch;
        while(scanf("%d", &a), a)
        {
            while(scanf("%d%c", &b, &ch))
            {
                G[a].push_back(b);
                G[b].push_back(a);
                if(ch=='\n')
                    break;
            }
        }
        solve();
    }
    return 0;
}

 

posted on 2016-07-14 19:37  南风丶丶  阅读(145)  评论(2编辑  收藏  举报