fafu 1181 割点

http://acm.fafu.edu.cn/problem.php?id=1181

 

View Code
//fafu 1181 割点

//题目很明了 就是求割点数

#include <stdio.h>
#include <string.h>

#define N 1005

int n_node, n_edge, cnt, ans;
int low[N], dep[N];
bool map[N][N];

void cutpoint(int son, int fa, int depth)
{
    cnt++;
    int branch = 0;
    dep[son] = low[son] = depth;
    for(int i = 1; i <= n_node; ++i)
    {   //son 可以到i 且 i不等于fa 才不会往回搜
        if(map[son][i] == true && i != fa)
        {
            if(dep[i] == 0)
            {   //若1 --> 2 -- > 3 --> 1 --> 4  有4这一分支时1是割点,没有4时,
                branch++; //1不是割点,所以1为起点的话要判断是否有两个或两个以上分支

                cutpoint(i, son, depth+1);
                //若父亲son所能到的最小层数 大于孩子i所能到的最小层数
                if(low[son] > low[i])   //则把son的最小层数更新为 i所
                    low[son] = low[i];  //能到的最小层数
                //若孩子所能到的最小层数大于等于父亲son所在的层数
                //或son为根节点(1)且分支数大于1,则son为割点
                if(low[i] >= dep[son] && son != 1|| son == 1 && branch > 1)
                    ans++;  //记得则里判断条件是 大于等于,而求割边数是这里是大于
            }
            else if(low[son] > low[i])
                low[son] = low[i];
        }
    }
}

int main()
{
    while(scanf("%d%d", &n_node, &n_edge) != EOF)
    {
        memset(map, false, sizeof(map));
        for(int i = 0; i < n_edge; ++i)
        {
            int a, b;
            scanf("%d%d", &a, &b);
            map[a][b] = map[b][a] = true;
        }

        ans = cnt = 0;
        memset(dep, 0, sizeof(dep));
        cutpoint(1, -1, 1); //令1 为根节点,-1为1的父亲,深度为1

        if(cnt < n_node)   //若遍历过的点数少于总的节点数(即不联通)
            puts("-1");
        else
            printf("%d\n", ans);
    }
    return 0;
}

 

posted @ 2012-04-21 23:32  gabo  阅读(175)  评论(0编辑  收藏  举报