POJ2762(判断无向图的弱连通)
题目:http://poj.org/problem?id=2762
题意:给出n个山洞,对于每个山洞,如果任意选择两点s,e,都满足s可以到达e或者e可以到达s,则输出Yes,否则输出No。
分析:实际上判断是否弱连通,所以首先强连通,然后缩点,对缩点形成的图最多只能有一个入度为0的点,如果有多个入度为
0的点,则这两个连通分量肯定是不连通的。缩点后形成的图形是一棵树,入度为0的点是这颗树的根,这棵树只能是单链,不
能有分叉,如果有分叉,则这些分叉之间是不可达的,所以就对这棵树进行DFS,如果是单链则是YES。
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
const int N = 10005;
struct Edge
{
int to;
Edge *next;
};
Edge *map1[N],*map2[N]; //分别保存原图和缩点后的图
int dfn[N],low[N],stack[N],belong[N],indeg[N];
int index,scc_num,top;
bool tmp[N];
int result[N];
void Tarjan(int u)
{
dfn[u] = low[u] = ++index;
stack[++top] = u;
tmp[u] = true;
for(Edge *p = map1[u]; p; p = p->next) //枚举每一条边
{
int v = p->to;
if(!dfn[v])
{
Tarjan(v); //dfs继续下找
low[u] = min(low[u],low[v]);
}
else if(tmp[v])
{
low[u] = min(low[u],dfn[v]);
}
}
if(low[u] == dfn[u]) //如果节点u是强连通分量的根
{
int t;
++scc_num; //强连通分量个数加1
do
{
t = stack[top--];
tmp[t] = false;
belong[t] = scc_num; //记录属于第几个强连通分量
}
while(t != u);
}
}
int Count(int n)
{
for(int i=1;i<=n;i++)
if(!dfn[i])
Tarjan(i);
return scc_num;
}
int Find() //在新图中找入度为0的点,如果只有一个就返回位置,否则返回0
{
int record;
int cnt = 0;
for(int i=1; i<=scc_num; i++)
{
if(indeg[i] == 0)
{
cnt++;
record = i;
}
}
if(cnt == 1) return record;
return 0;
}
bool TopSort()
{
int u,num = 0;
while(u = Find())
{
result[num++] = u;
indeg[u] = -1;
Edge *p = map2[u];
while(p)
{
indeg[p->to]--;
p = p->next;
}
}
if(num == scc_num) return true;
return false;
}
void Init()
{
index = 0;
top = 0;
scc_num = 0;
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(indeg,0,sizeof(indeg));
memset(tmp,false,sizeof(tmp));
memset(map1,NULL,sizeof(map1));
memset(map2,NULL,sizeof(map2));
memset(result,0,sizeof(result));
}
int main()
{
int T,m,n;
scanf("%d",&T);
while(T--)
{
Init();
scanf("%d%d",&n,&m);
while(m--)
{
int a,b;
scanf("%d%d",&a,&b);
Edge *p = new Edge();
p->to = b;
p->next = map1[a];
map1[a] = p;
}
int cnt = Count(n);
if(cnt == 1)
{
puts("Yes");
continue;
}
for(int i=1;i<=n;i++)
{
Edge *p = map1[i];
while(p)
{
if(belong[i] != belong[p->to])
{
indeg[belong[p->to]]++;
Edge *q = new Edge();
q->to = belong[p->to];
q->next = map2[belong[i]];
map2[belong[i]] = q;
}
p = p->next;
}
}
bool flag = false;
int ans = 0;
for(int i=1;i<=cnt;i++)
{
if(indeg[i] == 0)
ans++;
}
if(ans > 1) flag = false;
else if(TopSort()) flag = true;
if(flag) puts("Yes");
else puts("No");
}
return 0;
}
POJ2762(判断无向图的弱连通)相关推荐
- 判断图有无环_判断无向图/有向图中是否存在环
本文主要针对如何判断有向图/无向图中是否存在环的问题进行简单的论述. 一 无向图 1.利用DFS进行判断 利用DFS判断有向图是否存在环,是最为常用的一种方法,虽然这种方法很常用,但可参考的代码的实现 ...
- python找图里的环_python判断无向图环是否存在的示例
暂时是一个手动设置无向图中的边,用一个二维数组表示,后面会改进为用户自己定义无向图的边. 学习python的新手,若大佬有解决的办法,希望不吝赐教 #无向图判断环是否存在 def dfs(u,fa): ...
- Python 判断无向图是否存在环
代码实现 def has_cycle(G):"""判断无向图是否有环:param G: example {0: [1,2],1: [3], 2: []}:return:T ...
- 判断无向图是否有回路有四种方法
一.无向图回路的判断 对于无向图,判断其是否有回路有四种方法,如下所示: 1.利用深度优先搜索DFS,在搜索过程中判断是否会出现后向边(DFS中,连接顶点u到它的某一祖先顶点v的边),即在DFS ...
- 判断无向图G是否是一颗树
一个无向图是一颗树的条件是有n-1条边的连通图,n为图中顶点的个.边和顶点的数目是否满足条件可有图的信息直接判断,连通与否可以用遍历能否访问到所有顶点来判断. 结构体定义: #include<s ...
- 染色法判断无向图是否为二部图
二分图 二分图又称作二部图,是图论中的一种特殊模型. 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的 ...
- python中判断无向图是否有环_数据结构与算法:17 图
17 图 知识结构: 图1 知识结构 1. 图的基本概念与术语 1.1 图的定义 图由顶点集和边集组成,记为 . 顶点集:顶点的有穷非空集合,记为. 边集:顶点偶对的有穷集合,记为 . 边: 无向边: ...
- 有向图、无向图是否有环的判断
今天在做数据库的调度冲突可串行性判别的程序,中间要用到有向图中环判定的问题,特摘录如下.这些算法和思想都是来自网上的,在此感谢原作者! 先介绍一下无向图的判断算法,这个比较简单: 判断无向图中是否存在 ...
- 求无向图的连通分量或有向图的强连通分量—tarjan()ccf高速公路
概念定义: 在图论中,连通图基于连通的概念. 1. 连通(无向图): 若顶点Vi能通过路径到达Vj,那么称为Vi和Vj是连通的 对无向图:若从顶点Vi到顶点Vj有路径相连(当然从j到i也一定有路径), ...
最新文章
- Java 异常处理的 9 个最佳实践
- 未来十年是AI的黄金发展期
- bottle+jquery 前后端分离
- [机器学习]总结特征工程干货
- 老男孩shell实战读书笔记 (6-10章节)
- 枚举工具类 EnumUtils.java
- MySQL高可用之主备同步:javafor循环乘法表
- Struts2之异常处理
- Gogs代码托管系统安装配置手册
- Ingress.exe——今天你被监控了吗?
- PV-RCNN:Point-based与Voexl-based共同成就的高性能3D目标检测网络
- 计算机最最最底层的工作原理是怎么运行的
- 极坐标形式的复数计算器
- 背景是不规则图案css,CSS3 实现花式背景图案
- HTML语言剖析14:特殊字符
- 【Hadoop大数据分析与挖掘实战】(一)----------P19~22
- 分享创意个性古风剪影喜迎国庆PPT模板
- 6种不露脸的自媒体账号玩法,每一个变现都很强
- python编程培训多少钱-Python培训需要多少费用?
- 局域网找到计算机但无法访问磁盘,Win10系统不能访问局域网共享磁盘如何解决...