为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000),每个通道都是单向的,就是说若称某通道连通了A房间和B房间,只说明可以通过这个通道由A房间到达B房间,但并不说明通过它可以由B房间到达A房间。Gardon需要请你写个程序确认一下是否任意两个房间都是相互连通的,即:对于任意的i和j,至少存在一条路径可以从房间i到房间j,也存在一条路径可以从房间j到房间i。 

Input

输入包含多组数据,输入的第一行有两个数:N和M,接下来的M行每行有两个数a和b,表示了一条通道可以从A房间来到B房间。文件最后以两个0结束。 
Output

对于输入的每组数据,如果任意两个房间都是相互连接的,输出"Yes",否则输出"No"。 
Sample Input

3 3
1 2
2 3
3 1
3 3
1 2
2 3
3 2
0 0

Sample Output

Yes
No 题目大意:一个有向图,有n个点和m条边。判断整个图是否强连通,如果是,输出Yes,否则输出No。
题目可以用Kosaraju算法和Tarjan算法。
详解来自于:《算法竞赛 入门到进阶》
Kosaraju算法:
Kosaraju算法用到了“反图”的技术,基于下面两个原理:
(1)一个有向图G,把G所有的边反向,建立反图rG,反图rG不会改变原图G的强连通性。也就是说,图G的SCC数量与rG的SCC(强联通分量)数量相同。
(2)对原图G和反图rG各做一次DFS,可以确定SCC数量。 代码:
#pragma comment(linker, "/STACK:1024000000,1024000000")
#pragma GCC optimize(2)
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<cmath>
#include<string>
#include<map>
#include<vector>
#include<ctime>
#include<stack>
using namespace std;
#define mm(a,b) memset(a,b,sizeof(a))
typedef long long ll;
const long long mod = 1e9+;
const int maxn = 1e4+;
const int inf = 0x3f3f3f3f;
vector<int>G[maxn],rG[maxn];
vector<int>S;//存第一次dfs1的结果:标记点的先后顺序
int vis[maxn],sccno[maxn],cnt;//cnt为连通分量的个数 void dfs1(int u)
{
if(vis[u]) return;
vis[u]=;
for(int i=;i<G[u].size();i++) dfs1(G[u][i]);
S.push_back(u);//标记点的先后顺序,标记大的放在S的后面
} void dfs2(int u)
{
if(sccno[u]) return;
sccno[u]=cnt;
for(int i=;i<rG[u].size();i++) dfs2(rG[u][i]);
} void Kosaraju(int n)
{
cnt=;
S.clear();
mm(sccno,);
mm(vis,);
for(int i=;i<=n;i++) dfs1(i); //点的编号:1~n递归所有点
for(int i=n-;i>=;i--)
if(!sccno[S[i]])
{
cnt++;
dfs2(S[i]);
}
} int main()
{
int n,m,u,v;
while(scanf("%d %d",&n,&m),n||m)
{
for(int i=;i<n;i++)
{
G[i].clear();
rG[i].clear();
}
for(int i=;i<m;i++)
{
scanf("%d %d",&u,&v);
G[u].push_back(v);
rG[v].push_back(u);
}
Kosaraju(n);
if(cnt==) printf("Yes\n");
else printf("No\n");
}
return ;
}

Tarjan算法

上面的Kosaraju算法,其做法是从图中一个个地把SCC“挖”出来。Tarjan算法能在DFS中把所有点都按SCC分开。


 #pragma comment(linker, "/STACK:1024000000,1024000000")
#pragma GCC optimize(2)
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<cmath>
#include<string>
#include<map>
#include<vector>
#include<ctime>
#include<stack>
using namespace std;
#define mm(a,b) memset(a,b,sizeof(a))
typedef long long ll;
const long long mod = 1e9+;
const int maxn = 1e4+;
const int inf = 0x3f3f3f3f;
int cnt; //强连通分量的个数
int low[maxn],num[maxn],dfn;
int sccno[maxn];
stack<int>st;
vector<int>G[maxn]; void dfs(int u)
{
st.push(u);
low[u]=num[u]=++dfn;
for(int i=;i<G[u].size();i++)
{
int v=G[u][i];
if(!num[v]) //未访问过的点,继续DFS
{
dfs(v); //DFS的最底层,是最后一个SCC
low[u]=min(low[v],low[u]);
}
else if(!sccno[v]) //处理回退边
low[u]=min(low[u],num[v]);
}
if(low[u]==num[u]) //栈底的点是SCC的祖先,它的low=num
{
cnt++;
while()
{
int v=st.top(); //v弹出栈
st.pop();
sccno[v]=cnt;
if(u==v) break; //栈底的点是SCC的祖先
}
}
} void Tarjan(int n)
{
cnt=dfn=;
mm(sccno,);
mm(num,);
mm(low,);
for(int i=;i<=n;i++)
if(!num[i])
dfs(i);
} int main()
{
int n,m,u,v;
while(scanf("%d %d",&n,&m),n||m)
{
for(int i=;i<=n;i++) G[i].clear();
for(int i=;i<m;i++)
{
scanf("%d %d",&u,&v);
G[u].push_back(v);
}
Tarjan(n);
if(cnt==) printf("Yes\n");
else printf("No\n");
}
return ;
}

 

【强联通图 | 强联通分量】HDU 1269 迷宫城堡 【Kosaraju或Tarjan算法】的更多相关文章

  1. HDU 1269 迷宫城堡 (Kosaraju)

    题目链接:HDU 1269 Problem Description 为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000), ...

  2. HDU 1269 迷宫城堡(强连通)

    HDU 1269 迷宫城堡 pid=1269" target="_blank" style="">题目链接 题意:中文题 思路:强连通模板题 代 ...

  3. HDU 1269 迷宫城堡 (强连通分量,常规)

    题意: 判断所给的有向图是否是一个强连通图. 思路: 如果连通分量大于1则必定No,如果强连通分量大于1也是No.tarjan算法求强连通分量. #include <cstdio> #in ...

  4. hdu 1269 迷宫城堡

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=1269 迷宫城堡 Description 为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个 ...

  5. hdu 1269 迷宫城堡(强联通分量,基础)

    这是一道模版题 题目 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<string.h> #include ...

  6. hdu 1269 迷宫城堡 最简单的联通图题 kosaraju缩点算法

    迷宫城堡 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Problem Des ...

  7. HDU 1269 迷宫城堡(判断有向图强连通分量的个数,tarjan算法)

    迷宫城堡 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  8. hdu 1269 迷宫城堡 强连通分量

    迷宫城堡 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  9. HDU - 1269 迷宫城堡(有向图的强连通分量)

    d.看一个图是不是强连通图 s.求出强连通分量,看看有没有一个强连通分量包含所有点. c.Tarjan /* Tarjan算法 复杂度O(N+M) */ #include<iostream> ...

随机推荐

  1. 【iOS】图片缩放动画

    iOS 开发中,可用 UIView 的下述方法实现图片的缩放动画效果: + transitionWithView:duration:options:animations:completion: 示例代 ...

  2. Zabbix 中使用 Percona Monitoring Plugins 监控 MySQL

    1.先安装agent客户端 tar zxvf zabbix-3.2.6.tar.gz cd zabbix-3.2.6 ./configure --prefix=/data/zabbix --enabl ...

  3. 一看就懂的K近邻算法(KNN),K-D树,并实现手写数字识别!

    1. 什么是KNN 1.1 KNN的通俗解释 何谓K近邻算法,即K-Nearest Neighbor algorithm,简称KNN算法,单从名字来猜想,可以简单粗暴的认为是:K个最近的邻居,当K=1 ...

  4. Chrome谷歌浏览器实用插件

    总结整理了一下个人平时常用的谷歌浏览器插件 Adblock Plus 广告拦截  uBlock Origin Chrono 下载管理器 Tampermonkey 油猴子(各种强大的脚本,强烈推荐) F ...

  5. 【Java例题】7.3 线程题3-素数线程

    3.素数线程.设计一个线程子类,依次随机产生10000个随机整数(100-999):再设计另一个线程子类,依次对每一个随机整数判断是不是素数,是则显示:然后编写主类,在主函数中定义这两个线程类的线程对 ...

  6. java并发编程(二)----创建并运行java线程

    实现线程的两种方式 上一节我们了解了关于线程的一些基本知识,下面我们正式进入多线程的实现环节.实现线程常用的有两种方式,一种是继承Thread类,一种是实现Runnable接口.当然还有第三种方式,那 ...

  7. SprintBoot

    简述 推出时间:从Maven仓库的时间看是2016.7.28 目的:摆脱大量的XML配置文件以及复杂的Bean依赖关系,快速.敏捷地开发新一代基于Spring框架的应用程序 思想:约定优于配置(con ...

  8. 简洁实用Socket框架DotNettySocket

    目录 简介 产生背景 使用方式 TcpSocket WebSocket UdpSocket 结尾 简介 DotNettySocket是一个.NET跨平台Socket框架(支持.NET4.5+及.NET ...

  9. jQuery学习和知识点总结归纳

    jQuery目前在Web前端开发所占的比重越来越高,在我们jQuery学习和开发的过程中都会去使用.jQuery帮我们解决了浏览器之间JS一些不兼容的地方和简化了原生JS对DOM的操作.下面把PHP程 ...

  10. Javascript实现简单地发布订阅模式

    不论是在程序世界里还是现实生活中,发布—订阅模式的应用都非常广泛.我们先看一下现实中的例子. 小明最近看上了一套房子,到了售楼处之后才被告知,该楼盘的房子早已售罄.好在售楼MM告诉小明,不久后还有一些 ...