POJ 1523 SPF tarjan算法入门
注意:
对于生成树的每条边<u,v>:
u是割点的充要条件是:
1、若u为根节点, 它有2个以上包括两个的儿子(son >= 2)
2、u不为根节点,dfn[u] <= low[v];

#include<stdio.h> #include<string.h> #define maxn 1005 #define maxm maxn*maxn int min(int a, int b) { return a < b ? a : b;} int max(int a, int b) { return a > b ? a : b;} struct E { int v, next; }edge[maxm<<1]; int tot, head[maxn]; int n; void add(int s, int t) { edge[tot].v = t; edge[tot].next = head[s]; head[s] = tot++; edge[tot].v = s; edge[tot].next = head[t]; head[t] = tot++; } int low[maxn]; int sub[maxn]; // 去掉某个点后连通分量的个数 int dfn[maxn]; int id; void dfs(int u, int fa) //加了fa只是减少了计算时间,去掉不影响AC { int i, v; low[u] = dfn[u] = ++id; for(i = head[u]; i != -1; i = edge[i].next) { v = edge[i].v; if(v == fa) continue; if(!dfn[v]) { dfs(v, u); low[u] = min(low[u], low[v]); if(low[v] >= dfn[u]) sub[u]++; } else low[u] = min(low[u], dfn[v]); } } void init() { n = tot = id = 0; memset(head, -1, sizeof(head)); memset(dfn, 0, sizeof(dfn)); memset(sub, 0, sizeof(sub)); } int main() { int i, j, x, y, cas = 1; while( ~scanf("%d", &x) && x) { init(); scanf("%d", &y); add(x, y); n = max(n, max(x, y)); while( ~scanf("%d", &x) && x) { scanf("%d", &y); n = max(n, max(x, y)); add(x, y); } dfs(1, -1); printf("Network #%d\n", cas++); sub[1]--; // 根节点特殊处理 bool flag = 0; for(i = 1; i <= n; i++) { if(sub[i] >= 1) { printf(" SPF node %d leaves %d subnets\n", i, sub[i]+1); flag = 1; } } if(!flag) printf(" No SPF nodes\n"); puts(""); } return 0; }