HDU1269 有向图强连通分量

题目大意:问一个有向图是否任意两点在两个方向上互相连通。

有向图强连通分量定义:如果一个图中的任意两点在两个方向上都互相连通,则该图为强连通图。极大强连通图为有向图的强连通分量(注意是极大,不是最大。一个图会有多个强连通分量)。感性理解,强连通图就是多个环,或者一个点连接在一起所产生的图。

如何求?定义节点cur->Low,cur的子搜索树节点a中如果存在边(a,b),使得b->DfsN小于cur->DfsN,则cur->Low=min foreach b{b->DfsN},否则为cur->DfsN。显然,cur->Low所对应的节点位于cur所在极大强连通分量中,且是cur所在环中深度最浅的。

新定义一个栈维护一组节点,其使得处理完栈内节点cur以上的节点后,cur以上节点的Low <= cur->Low(它们位于cur子搜索树中的各个枝杈上(而不仅仅存在于一个枝杈中,这是系统栈所做不到的),不存在满足该条件却不在该栈内的节点),即cur及以上节点在一个强连通分量内。如果cur->Low == cur->DfsN,则cur是其所在强连通分量中深度最浅的,再往栈下面走的节点就不属于这个连通分量了,此时便可以输出连通分量,然后将cur及以上节点全部弹出。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

const int MAX_NODE = 10010, MAX_EDGE = 100010;

struct Node;
struct Edge;

struct Node
{
	int Id, DfsN, Low;
	Edge *Head;
}_nodes[MAX_NODE], *Root;
int _vCount, DfsCnt;

struct Edge
{
	Node *From, *To;
	Edge *Next;
	Edge() {}
}*_edges[MAX_EDGE];
int _eCount;


Edge *NewEdge()
{
	_eCount++;
	return _edges[_eCount] ? _edges[_eCount] : _edges[_eCount] = new Edge();
}

Edge *AddEdge(Node *from, Node *to)
{
	Edge *e = NewEdge();
	e->From = from;
	e->To = to;
	e->Next = from->Head;
	from->Head = e;
	return e;
}

vector<Node*> Stack;

void Init(int vCount)
{
	_vCount = vCount;
	_eCount = 0;
	DfsCnt = 0;
	Root = 1 + _nodes;
	Stack.clear();
	memset(_nodes, 0, sizeof(_nodes));
}

void Dfs(Node *cur)
{
	cur->DfsN = cur->Low = ++DfsCnt;
	Stack.push_back(cur);
	for (Edge *e = cur->Head; e; e = e->Next)
	{
		if (!e->To->DfsN)
		{
			Dfs(e->To);
			cur->Low = min(cur->Low, e->To->Low);
		}
		else
			cur->Low = min(cur->Low, e->To->DfsN);
	}
	if (cur != Root && cur->Low == cur->DfsN)
	{
		while (Stack.back() != cur)
			Stack.pop_back();
		Stack.pop_back();
	}
}

int main()
{
#ifdef _DEBUG
	freopen("c:\\noi\\source\\input.txt", "r", stdin);
	freopen("c:\\noi\\source\\output.txt", "w", stdout);
#endif
	int totNode, totEdge, uId, vId;
	while (scanf("%d%d", &totNode, &totEdge) && (totNode || totEdge))
	{
		Init(totNode);
		for (int i = 1; i <= totEdge; i++)
		{
			scanf("%d%d", &uId, &vId);
			_nodes[uId].Id = uId;
			_nodes[vId].Id = vId;
			AddEdge(uId + _nodes, vId + _nodes);
		}
		Dfs(Root);
		if (Stack.size()!=totNode)
			printf("No\n");
		else
			printf("Yes\n");
	}
	return 0;
}

  

posted @ 2018-02-24 14:55  headboy2002  阅读(136)  评论(0编辑  收藏  举报