fafu 1180 割边

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

View Code
//fafu 1180  割边

//low[i]表示i或i的子孙可以到达的最小深度
//若可到达的最小深度比父亲节点的深度来的高,则出现割边

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

#define N 1005

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

void cutline(int son, int fa, int dep)
{
    low[son] = depth[son] = dep;

    for(int i = 1; i <= n_node; ++i)
    {   //i!=fa 表示不能往回搜
        if(i != fa && map[son][i] == true)
        {
            if(depth[i] == 0)   //相当于标记是否遍历过
            {
                cnt++;  //记录遍历过的点数,若小于总的点数则不联通

                cutline(i, son, dep+1);
                //回溯回来,若儿子能到的深度比父亲的低,则
                //父亲指向儿子所指向的深度
                if(low[son] > low[i])
                    low[son] = low[i];
        //若儿子节点 i指向的最小深度大于父节点son的深度则为割边
                if(low[i] > depth[son])
                    ans++;
            }   //如果i 节点遍历过了(即表示形成环),则看son节点指向的最小深度
            else if(low[son] > low[i])  //有没有小于 i指向的最小深度,现在i 是son的孩子
                low[son] = low[i];   //则把 son指向的最小深度 更改为 i指向的最小深度
        }
    }
}

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;
        }

        cnt = 1;
        ans = 0;
        memset(depth, 0, sizeof(depth));
        cutline(1, -1, 1);  //令 1为根节点,-1为1 的父节点
        if(cnt < n_node)
            puts("-1");
        else
            printf("%d\n", ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/gabo/p/2461284.html