UVA315_Network _无向图割点::Tarjan

来源:互联网 发布:学一门编程语言要多久 编辑:程序博客网 时间:2024/06/11 14:57

题意

给出一个无向图,求割点。

思路

割点有两种情况:
1.根节点有两个以上子树,则根节点是割点
2.某个点的子树的回边不能连到该点之上,则该点是割点
判断这两种情况用的是Tarjan算法。
对于第二种情况,只需要判断 Root[v] <= Mark[u]。

题目链接

VJudge中的链接
https://vjudge.net/contest/169043#problem/B

AC代码

#include<cstdio>#include<iostream>#include<cstring>#include<vector>using namespace std;const int maxn = 100 + 10;int N;int Ans;char Str[300];vector<int> G[maxn];int Mark[maxn], Root[maxn];bool Ap[maxn];int Index;void Tarjan(int u, int pre){    Mark[u] = Root[u] = ++ Index;    int nchild = 0;    for(int i= 0; i< G[u].size(); i++)    {        int v = G[u][i];        if(Mark[v] == 0)        {            nchild ++;            Tarjan(v, u);            if(Root[v] < Root[u]) Root[u] = Root[v];            if(pre == -1 && nchild > 1) Ap[u] = true;            else if(pre != -1 && Root[v] >= Mark[u]) Ap[u] = true;        }        else if(v != pre && Mark[v] < Root[u]) Root[u] = Mark[v];    }}int FAP(){    memset(Mark, 0, sizeof Mark);    memset(Root, 0, sizeof Root);    memset(Ap, false, sizeof Ap);    Index = 0;    Tarjan(1, -1);    int ret = 0;    for(int i= 1; i<= N; i++)        if(Ap[i]) ret ++;    return ret;}int main(){    while(scanf("%d", &N), N)    {        for(int i= 1; i<= N; i++) G[i].clear();        int s, x;        while(scanf("%d", &s), s)        {            char c;            while(1)            {                scanf("%d%c", &x, &c);                G[x].push_back(s);                G[s].push_back(x);                if(c == '\n') break;            }        }        printf("%d\n", FAP());    }    return 0;}
原创粉丝点击