简单的无向图求割点.
代码如下:
#include <cstdlib> #include <cstring> #include <cstdio> #include <algorithm> #define MAXN 1005 using namespace std; int head[MAXN], idx, LIM, dfn[MAXN], low[MAXN], ti; int subnet[MAXN]; bool vis[MAXN]; struct Edge { int v, next; }e[MAXN*MAXN]; void AddEdge(int x, int v) { ++idx; e[idx].v = v, e[idx].next = head[x]; head[x] = idx; } void dfs(int u) { // low 值一定是越低越好 for (int i = head[u]; i != -1; i = e[i].next) { if (!vis[e[i].v]) { vis[e[i].v] = true; dfn[e[i].v] = low[e[i].v] = ++ti; dfs(e[i].v); low[u] = min(low[u], low[e[i].v]); if (low[e[i].v] == dfn[u]) { // 孩子中不存在抵达上层的其他途径 ++subnet[u]; } } else { low[u] = min(low[u], dfn[e[i].v]); } } } void solve() { bool flag = false; memset(vis, false, sizeof (vis)); memset(subnet, 0, sizeof (subnet)); subnet[1] = -1; vis[1] = true; // 由于图一定是联通的,所以就一定能够找到所有的点 dfn[1] = low[1] = ++ti; dfs(1); for (int i = 1; i <= LIM; ++i) { if (subnet[i] > 0) { printf(" SPF node %d leaves %d subnets\n", i, subnet[i]+1); flag = 1; } } if (!flag) { puts(" No SPF nodes"); } } int main() { int a, b, ca = 0; bool indata = false, first = true; LIM = ti = 0, idx = -1; memset(head, 0xff, sizeof (head)); while (1) { scanf("%d", &a); LIM = max(LIM, a); if (!a) { if (!indata) break; else { if (first) { first = false; } else { puts(""); } indata = false; printf("Network #%d\n", ++ca); solve(); LIM = ti = 0, idx = -1; // 一个初始化 memset(head, 0xff, sizeof (head)); continue; } } indata = true; scanf("%d", &b); // 表示a,b之间有一条无向边 LIM = max(LIM, b); // 找到最大的顶点编号 AddEdge(a, b); AddEdge(b, a); // 无向图的双向边 } return 0; }