poj2186

Tarjan模板题。建议采用二维vector存储。

学习Tarjan时要注意两个数组:

int DFN[M]; //深度优先搜索访问次序  int Low[M]; //能追溯到的最早的次序 

这是学习的网址:http://www.nocow.cn/index.php/Tarjan算法

P.s. Tarjan真心是递归之精髓的体现啊!

下面是标准的Tarjan的模板。

这道题算法其实很清楚,把图的边反向存储,再把图的强连通分量求出来,然后找出入度为零的分量,如果入度为0的强连通分量个数大于1,那么最终解一定是0,否则最终解就是那个入度为零的强连通分量的点的个数。

#include <iostream>
#include <string.h>
#include <vector>

#define MAX_N 10010
#define MAX_M 50010

using namespace std;

vector <int> vec[MAX_N];

int dfn[MAX_N], low[MAX_N], stap[MAX_N], belong[MAX_N];
int n, m, bcnt, dindex = 0, stop = 0;
int rd[MAX_N], rd0cnt;
bool instack[MAX_N];

int x[MAX_M], y[MAX_M];

void tarjan(int v) {
	int u, l = vec[v].size();
	dfn[v] = low[v] = ++dindex;
	instack[v] = true;
	stap[++stop] = v;
	for (int i = 0; i < l; i++) {
		u = vec[v][i];
		if (!dfn[u]) {
			tarjan(u);
			if (low[u] < low[v])
				low[v] = low[u];
		}
		else if (instack[u] && dfn[u] < low[v])
			low[v] = dfn[u];
	}
	if (dfn[v] == low[v]) {
		bcnt++;
		do {
			u = stap[stop--];
			instack[u] = false;
			belong[u] = bcnt;
		}
		while (u != v);
	}
}

int main() {
	while (cin >> n >> m) {
		for (int i = 1; i <= m; i++) {
			cin >> x[i] >> y[i];
			vec[y[i]].push_back(x[i]);
		}
		stop = bcnt = dindex = 0;
		memset(dfn, 0, sizeof(dfn));
		for (int i = 1; i <= n; i++)
			if (!dfn[i]) tarjan(i);
		memset(rd, 0, sizeof(rd));
		for (int i = 1; i <= m; i++)
			if (belong[x[i]] != belong[y[i]])
				rd[belong[x[i]]]++;
		int cnt = 0;
		for (int i = 1; i <= bcnt; i++)
			if (rd[i] == 0) cnt++;
		if (cnt > 1) cout << 0 << endl;
		else {
			cnt = 0;
			for (int i = 1; i <= n; i++)
				if (rd[belong[i]] == 0) cnt++;
			cout << cnt << endl;
		}
	}
}


你可能感兴趣的:(图论,ACM题解报告)