为了训练小希的方向感,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. dz6.0的一个sql注入漏洞

    今天开始着手分析第一个漏洞,找了一上午靶机,发现一个含有成人内容的违法网站是用dz6.0搭的,今天就看看dz这个版本的洞了 问题函数位置:my.php第623行 if(is_array($descri ...

  2. 【iOS】安装 CocoaPods

    1. 打开 terminal 2. 移除现有 Ruby 默认源 $ gem sources --remove https://rubygems.org/ 3. 使用新的源 $ gem sources ...

  3. ProcessBuilder waitFor 调用外部应用

    小程序项目最初使用ffmpeg转换微信录音文件为wav格式,再交给阿里云asr识别成文字.视频音频转换最常用是ffmpeg. 1 ffmpeg -i a.mp3 b.wav 相关文章: 小程序实现语音 ...

  4. cesium学习——cesium中的坐标

    一.坐标展现形式 在cesium中,对于坐标数值单位有三种:角度.弧度和坐标值 1.角度 角度就是我们所熟悉的经纬度,对于地球的坐标建立如下: 图中以本初子午线作为x和z的面,建立了一个空间坐标系.可 ...

  5. Unity经典游戏教程之:贪吃蛇

    版权声明: 本文原创发布于博客园"优梦创客"的博客空间(网址:http://www.cnblogs.com/raymondking123/)以及微信公众号"优梦创客&qu ...

  6. koa2基于stream(流)进行文件上传和下载

    阅读目录 一:上传文件(包括单个文件或多个文件上传) 二:下载文件 回到顶部 一:上传文件(包括单个文件或多个文件上传) 在之前一篇文章,我们了解到nodejs中的流的概念,也了解到了使用流的优点,具 ...

  7. 高性能MySQL之事物

    一.概念 事务到底是什么东西呢?想必大家学习的时候也是对事务的概念很模糊的.接下来通过一个经典例子讲解事务. 银行在两个账户之间转账,从A账户转入B账户1000元,系统先减少A账户的1000元,然后再 ...

  8. 集成方法 Ensemble

    一.bagging 用于基础模型复杂.容易过拟合的情况,用来减小 variance(比如决策树).基础模型之间没有太多联系(相对于boosting),训练可以并行.但用 bagging 并不能有助于把 ...

  9. Docker之- 使用Docker 镜像和仓库

    目录 使用Docker 镜像和仓库 什么是 Docker 镜像 列出 Docker 镜像 tag 标签 Docker Hub 拉取镜像 查找镜像 构建镜像 创建Docker Hub 账号 使用 Doc ...

  10. Intellij IDEA 2019.2 设置Git

    点击File选择Settings 查找Git 选择Git安装路径bin目录下git.exe并点击text是否可用 选择OK安装完成. IDEA 拉去github 或 gogs上的项目(选择VCS —— ...