类型:图的割点
题目:http://poj.org/problem?id=1523
思路:构图,通过dfs【Tarjan算法】记录各个顶点的深度优先数,在回退的过程中记录low数组,如果孩子节点low值大于等于父节点step值,记录分割的联通分量的个数
!!!输出格式
// poj 1523 SPF
// ac 1164K 16MS
#include <iostream>
#include <string>
#include <cstring>
#include <cstdio>
#include <cstdlib>
using namespace std;
#define MAXN 1005
typedef long long LL;
bool sign;
bool vis[MAXN];
bool tu[MAXN][MAXN];
int cnt, maxn;
int subsets[MAXN], low[MAXN], step[MAXN];
void init() {
memset(vis, false, sizeof(vis));
memset(step, -1, sizeof(step));
memset(subsets, 0, sizeof(subsets));
low[1] = step[1] = cnt = 1;
vis[1] = true;
}
void dfs(int u) {
int v;
for(v = 1; v <= maxn; ++v) {
if(tu[u][v]) {
if(!vis[v]) {
vis[v] = true;
low[v] = step[v] = (++cnt);
dfs(v);
low[u] = min(low[u], low[v]);
if(low[v] >= step[u])
subsets[u]++;
}
else
low[u] = min(low[u], step[v]);
}
}
}
int main() {
int i, u, v;
int num = 1;
while(scanf("%d", &u) == 1, u) {
maxn = 0;
sign = false;
memset(tu, false, sizeof(tu));
scanf("%d", &v);
if(maxn < u) maxn = u;
if(maxn < v) maxn = v;
tu[u][v] = tu[v][u] = true;
while(scanf("%d", &u) == 1, u) {
scanf("%d", &v);
if(maxn < u) maxn = u;
if(maxn < v) maxn = v;
tu[u][v] = tu[v][u] = true;
}
init();
dfs(1);
if(num > 1)
printf("\n");
printf("Network #%d\n", num++);
if(subsets[1] >= 2){
sign = true;
printf(" SPF node %d leaves %d subnets\n", 1, subsets[1]);
}
for(i = 2; i <= maxn; ++i) {
if(subsets[i]) {
sign = true;
printf(" SPF node %d leaves %d subnets\n", i, subsets[i] + 1);
}
}
if(!sign)
printf(" No SPF nodes\n");
}
return 0;
}