poj 2186 popular cows 求强连通分量

好久没写了,最近发懒,加上大部分时间都在做学校的voj,倒是很少想起来这儿发帖了。昨天刚考完oj,10道题只A了3道,但也算比去年有进步吧。。感觉我回头还应该自学些高级数据结构,否则根本应付不过来。

今天发现学校oj论坛上有一道poj 2186的题,一看大概是要求强连通分量来把图缩成树处理,然而网上大部分解法都是Tarjan或者Torasaju。。。我就查了下算法导论,第二十二章倒也提到过一种做法,就是先dfs,然后按回溯时间由后到前在其补图上再跑一遍dfs,这一遍能够保证没有横向边,从而能够做到将其正确输出。学校oj也是坑人,poj上已经过了,然而这边一直WA,后来把while scanf那一句去掉一下就过了,无法理解了。。。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
#define MAXN 10010
#define MAXE 50010
typedef int Edge;
typedef pair Ele;
typedef long long ll;
int outDegree[MAXN];
Ele finishTime[MAXN];
int order[MAXN];
class binGraph
{//graph with ante graph
public:
	binGraph(int nn, int mm) :n(nn), m(mm)
	{
		for (int i = 0; i < n; i++) 
			edges[0][i].clear();
		for (int i = 0; i < n; i++)
			edges[1][i].clear();
		for (int i = 0; i < m; i++) {
			int u, v;
			scanf("%d %d", &u, &v);
			_addEdge(u - 1, v - 1, 1);
		}
		memset(_componentSize, 0, sizeof(_componentSize));
		memset(finishTime, 0, sizeof(finishTime));
	}
	void dfs(int No,Ele finishArray[],int order[])
	{
		memset(visited, 0, sizeof(visited));
		_finishTime = 0;
		int componentName = 0;
		for (int i = 0; i < n; i++) {
			int u = order == NULL ? i : order[i];
			if (!visited[u]) {
				int compoSize=_dfs(No, u, finishArray, componentName);
				_componentSize[componentName++] = compoSize;
			}
		}
		_sccNumber = componentName;
	}
	void rebuild()
	{//before graphs discarded
		memset(outDegree, 0, sizeof(outDegree));
		for (int i = 0; i < n; i++) {
			int u = _componentName[i];
			for (int j = 0; j < edges[0][i].size(); j++) {
				int v = _componentName[edges[0][i][j]];
				if ((u!=v)) {
					outDegree[u]++;
				}
			}
		}
		n = _sccNumber;
		int ans = 0;
		int count = 0;
		for (int i = 0; i < n; i++) {
			if (outDegree[i] == 0) {
				count++;
				ans = _componentSize[i];
			}
		}
		printf("%d\n", count == 1 ? ans : 0);
	}
private:
	int n, m;
	vector edges[2][MAXN];
	bool visited[MAXN];
	int _finishTime;
	int _sccNumber;
	int _componentName[MAXN];
	int _componentSize[MAXN];
	void _addEdge(int u, int v, int w)
	{//w ignored here
		edges[0][u].push_back(v);
		edges[1][v].push_back(u);//ante graph
	}
	int _dfs(int No, int s, Ele finishArray[], int sccNumber)
	{
		int ret = 0;
		stack dfsStack;
		while (dfsStack.empty() == false)
			dfsStack.pop();
		dfsStack.push(s);
		while (!dfsStack.empty()) {
			int u = dfsStack.top();
			visited[u] = true;
			bool visitAll = true;
			for (int i = 0; i < edges[No][u].size(); i++) {
				int v = edges[No][u][i];
				if (!visited[v]) {
					visitAll = false;
					visited[v] = true;
					dfsStack.push(v);
				}
			}
			if (visitAll) {
				finishArray[u].first = _finishTime++;
				_componentName[u] = sccNumber;
				dfsStack.pop();
				ret++;
			}
		}
		return ret;
	}
};
bool comp(Ele e1, Ele e2)
{
	return e1.first > e2.first;
}
int main()
{
	int n, m;
	scanf("%d %d", &n, &m);
	binGraph bg(n, m);
	for (int i = 0; i < n; i++)
		finishTime[i].second = i;
	bg.dfs(0, finishTime, NULL);
	sort(finishTime, finishTime + n, comp);
	for (int i = 0; i < n; i++)
		order[i] = finishTime[i].second;
	bg.dfs(1, finishTime, order);//sort anteGraph bon defiAjo
	bg.rebuild();
	return 0;
}
现在poj累计38道题了。。。路漫漫其修远兮啊

你可能感兴趣的:(scc,poj,2186,oj,odyssey)