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

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

如何求?定义节点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;
}

  

最新文章

  1. Base64 转换 %2B 变 空格 解决
  2. Redis常用命令
  3. Mac终端用Sublime打开指定文件或文件夹
  4. Visual Studio 2013 (vs2013)中“向前定位”,“向后定位”按钮
  5. WooCommerce代码收集
  6. wordpress安装,创建配置文件无反应
  7. linux - 开机启动thunderbird、chromium
  8. TCP/IP详解学习笔记(1)-基本概念
  9. Hibernate 二级缓存 总结整理(转)
  10. delete删除多表
  11. main函数的3个参数
  12. 用Javascript的for循环输出质数
  13. Css 应用一
  14. Swift - 运算符重载和运算符函数
  15. hdu1011(树形背包)
  16. React和动态网站接口的经济学
  17. Java_基础篇(数组的反转)
  18. Python内置函数(68)——__import__
  19. Windows 系统判断MD5 值的办法
  20. JavaStudy——Java之自动拆箱与自动装箱

热门文章

  1. 复习HTML+CSS(8)
  2. matplotlib之pyplot 知识点滴
  3. 努比亚(nubia) V18 NX612J 解锁BootLoader 并刷入recovery ROOT
  4. 在 ef 中执行 DbContext.Table.AddRange(Enitites).ToList() 会发生什么
  5. (1)dotnet开源电商系统-brnshop&amp;brnMall 和老外开发的nopCommerce(dotnet两套电商来PK--第一篇)
  6. 个人作业—Alpha测试
  7. ApplicationLoader登录失败
  8. 上传菜品数据&amp;生成点餐二维码
  9. 国密SSL证书申请免费试用
  10. Python学习笔记之类与对象