zoukankan      html  css  js  c++  java
  • 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
    ");
    		else
    			printf("Yes
    ");
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    php单例模式
    php编码规范
    mysql_affected_rows的注意点
    ThinkPHP的sql_mode的默认设置,导致无效信息被插入
    InnoDB事务和锁
    php中const和static的区别和联系
    php 位运算符的实际应用(权限判断)
    使用LBS(地理位置)
    OkHttpClient简单封装
    Gson解析json
  • 原文地址:https://www.cnblogs.com/headboy2002/p/8465809.html
Copyright © 2011-2022 走看看