POJ1144 Network 无向图的割顶

现在打算重新学习图论的一些基础算法,包括像桥,割顶,双连通分量,强连通分量这些基础算法我都打算重敲一次,因为这些量都是可以用tarjan的算法求得的,这次的割顶算是对tarjan的那一类算法的理解的再次实现吧,后面打算做一下桥的判断和边双连通的关系,边双连通处理的时候如果又重边的话会很不一样,割顶也会相应的不一样,这里的代码是没有考虑重边的,后面再写一个考虑重边的吧。

#pragma warning(disable:4996)
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<cmath>
#define maxn 150
using namespace std;

vector<int> G[maxn];
int n;
int low[maxn], pre[maxn];
int dfs_clock;
bool iscut[maxn];

int dfs(int u, int fa)
{
	int lowu = pre[u] = ++dfs_clock; int ch = 0;
	for (int i = 0; i < G[u].size(); i++){
		int v = G[u][i];
		if (!pre[v]){
			ch++;
			int lowv=dfs(v, u);
			lowu = min(lowu, lowv);
			if (lowv >= pre[u]){
				iscut[u] = true;
				//if (lowv>pre[u]) (u,v)是桥
			}
		}
		else if (pre[v] < pre[u] && v != fa){
			lowu = min(lowu, pre[v]);
		}
	}
	if (fa < 0 && ch == 1) iscut[u] = false;
	return low[u] = lowu;
}

void init()
{
	memset(low, 0, sizeof(low));
	memset(pre, 0, sizeof(pre));
	memset(iscut, 0, sizeof(iscut));
	dfs_clock = 0;
	for (int i = 1; i <= n; i++){
		if (!pre[i]) dfs(i, -1);
	}
}

int main()
{
	while (cin >> n&&n)
	{
		for (int i = 0; i <= n; i++) G[i].clear();
		int a,b; char c;
		while (scanf("%d", &a)==1&&a){
			while ((c = getchar()) != '
'){
				scanf("%d", &b);
				G[a].push_back(b);
				G[b].push_back(a);
			}
		}
		init(); int ans = 0;
		for (int i = 1; i <= n; i++){
			if (iscut[i]) ans++;
		}
		printf("%d
", ans);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/chanme/p/3563876.html