【强联通图 | 强联通分量】HDU 1269 迷宫城堡 【Kosaraju或Tarjan算法】
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算法】的更多相关文章
- HDU 1269 迷宫城堡 (Kosaraju)
题目链接:HDU 1269 Problem Description 为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000), ...
- HDU 1269 迷宫城堡(强连通)
HDU 1269 迷宫城堡 pid=1269" target="_blank" style="">题目链接 题意:中文题 思路:强连通模板题 代 ...
- HDU 1269 迷宫城堡 (强连通分量,常规)
题意: 判断所给的有向图是否是一个强连通图. 思路: 如果连通分量大于1则必定No,如果强连通分量大于1也是No.tarjan算法求强连通分量. #include <cstdio> #in ...
- hdu 1269 迷宫城堡
题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=1269 迷宫城堡 Description 为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个 ...
- hdu 1269 迷宫城堡(强联通分量,基础)
这是一道模版题 题目 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<string.h> #include ...
- hdu 1269 迷宫城堡 最简单的联通图题 kosaraju缩点算法
迷宫城堡 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Problem Des ...
- HDU 1269 迷宫城堡(判断有向图强连通分量的个数,tarjan算法)
迷宫城堡 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- hdu 1269 迷宫城堡 强连通分量
迷宫城堡 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- HDU - 1269 迷宫城堡(有向图的强连通分量)
d.看一个图是不是强连通图 s.求出强连通分量,看看有没有一个强连通分量包含所有点. c.Tarjan /* Tarjan算法 复杂度O(N+M) */ #include<iostream> ...
随机推荐
- dz6.0的一个sql注入漏洞
今天开始着手分析第一个漏洞,找了一上午靶机,发现一个含有成人内容的违法网站是用dz6.0搭的,今天就看看dz这个版本的洞了 问题函数位置:my.php第623行 if(is_array($descri ...
- 【iOS】安装 CocoaPods
1. 打开 terminal 2. 移除现有 Ruby 默认源 $ gem sources --remove https://rubygems.org/ 3. 使用新的源 $ gem sources ...
- ProcessBuilder waitFor 调用外部应用
小程序项目最初使用ffmpeg转换微信录音文件为wav格式,再交给阿里云asr识别成文字.视频音频转换最常用是ffmpeg. 1 ffmpeg -i a.mp3 b.wav 相关文章: 小程序实现语音 ...
- cesium学习——cesium中的坐标
一.坐标展现形式 在cesium中,对于坐标数值单位有三种:角度.弧度和坐标值 1.角度 角度就是我们所熟悉的经纬度,对于地球的坐标建立如下: 图中以本初子午线作为x和z的面,建立了一个空间坐标系.可 ...
- Unity经典游戏教程之:贪吃蛇
版权声明: 本文原创发布于博客园"优梦创客"的博客空间(网址:http://www.cnblogs.com/raymondking123/)以及微信公众号"优梦创客&qu ...
- koa2基于stream(流)进行文件上传和下载
阅读目录 一:上传文件(包括单个文件或多个文件上传) 二:下载文件 回到顶部 一:上传文件(包括单个文件或多个文件上传) 在之前一篇文章,我们了解到nodejs中的流的概念,也了解到了使用流的优点,具 ...
- 高性能MySQL之事物
一.概念 事务到底是什么东西呢?想必大家学习的时候也是对事务的概念很模糊的.接下来通过一个经典例子讲解事务. 银行在两个账户之间转账,从A账户转入B账户1000元,系统先减少A账户的1000元,然后再 ...
- 集成方法 Ensemble
一.bagging 用于基础模型复杂.容易过拟合的情况,用来减小 variance(比如决策树).基础模型之间没有太多联系(相对于boosting),训练可以并行.但用 bagging 并不能有助于把 ...
- Docker之- 使用Docker 镜像和仓库
目录 使用Docker 镜像和仓库 什么是 Docker 镜像 列出 Docker 镜像 tag 标签 Docker Hub 拉取镜像 查找镜像 构建镜像 创建Docker Hub 账号 使用 Doc ...
- Intellij IDEA 2019.2 设置Git
点击File选择Settings 查找Git 选择Git安装路径bin目录下git.exe并点击text是否可用 选择OK安装完成. IDEA 拉去github 或 gogs上的项目(选择VCS —— ...