不多说,操作都是在核心算法的基础上变化,关键的判断 low[v] dfn[u] 之间的关系判段
poj 3177
/* * this code is made by LinMeiChen * Problem: * Type of Problem: * Thinking: * Feeling: */ #include<iostream> #include<algorithm> #include<stdlib.h> #include<string.h> #include<stdio.h> #include<math.h> #include<string> #include<vector> #include<queue> #include<list> using namespace std; typedef long long lld; typedef unsigned int ud; #define oo 0x3f3f3f3f #define maxn 5001 #define maxm 20002 struct Edge { int v, next; }E[maxn]; int head[maxn], parent[maxn]; int low[maxn], dfn[maxn]; int mark[maxn], bridge[maxn][2]; int belong[maxn], d[maxn]; int con, bg, n, tol; int find(int x) { if (x == parent[x]) return x; return parent[x] = find(parent[x]); } void merge(int x, int y) { int fx = find(x); int fy = find(y); parent[fx] = fy; } void DFS(int u, int fa, int dep) { mark[u] = 1; low[u] = dfn[u] = dep; for (int i = head[u]; i != -1; i = E[i].next) { int v = E[i].v; if (mark[v] == 0) { DFS(v, u, dep + 1); low[u] = min(low[u], low[v]); if (low[v] > dfn[u]) { bridge[bg][0] = u; bridge[bg][1] = v; bg++; } else merge(u, v); } else if (v != fa && mark[v] == 1) low[u] = min(low[u], dfn[v]); } mark[u] = 2; } void Con_num() { for (int i = 0; i <= n; i++) parent[i] = i; memset(mark, 0, sizeof mark); memset(dfn, 0, sizeof dfn); memset(low, 0, sizeof low); memset(belong, -1, sizeof belong); bg = 0; con = 0; DFS(1, -1, 1); for (int i = 1; i <= n; i++) { int fa = find(i); if (belong[fa] == -1) belong[fa] = ++con; belong[i] = belong[fa]; } } void add_edge(int u, int v) { E[tol].v = v; E[tol].next = head[u]; head[u] = tol++; } int main() { int m, u, v; while (scanf("%d%d", &n, &m) != EOF) { memset(head, -1, sizeof head); tol = 0; for (int i = 1; i <= m; i++) { scanf("%d%d", &u, &v); add_edge(u, v); add_edge(v, u); } Con_num(); memset(d, 0, sizeof d); for (int i = 0; i < bg; i++) { u = bridge[i][0]; v = bridge[i][1]; d[belong[u]]++; d[belong[v]]++; } int cnt = 0; for (int i = 1; i <=con;i++) if (d[i] == 1) cnt++; printf("%d\n", (cnt + 1) / 2); } return 0; }