http://acm.fafu.edu.cn/problem.php?id=1180
//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; }