【强联通图 | 强联通分量】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> ...
随机推荐
- poj2909 欧拉素数筛选
刚刚学了一种新的素数筛选法,效率比原先的要高一些,据说当n趋近于无穷大时这个的时间复杂度趋近O(n).本人水平有限,无法证明. 这是道水题,贴代码出来重点是欧拉筛选法.我把原来普通的筛选法贴出来. / ...
- memCached的配置文件 配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...
- StarUML 3.0 破解方法
首先在我这里下载 StarUML3.0 破解替换文件app.asar 链接:https://pan.baidu.com/s/1wDMKDQkKrE9D1c0YeXz0xg 密码:y65m 然后参照下 ...
- 监控LVS
监控LVS #!/usr/bin/python-2.6.6 #data 2017-10-17 #auth liuchao import commands,os,time #-------------- ...
- Linux系统下减少LV(逻辑卷)容量
查看文件系统现有 lv_test 容量,总计9.9G,已使用2% 命令 df -h 2 查看系统中的 PV 情况 命令:pvdisplay vg_test 下有两个 PV,分别为 /dev/sdb1 ...
- 夯实Java基础(七)——Static关键字
1.static介绍 static关键字一直是各大企业中面试常常会问到的问题,主要考察面试者的基础是否扎实,下面来介绍一下static关键字. Java中static表示“全局”或者“静态”的意思,可 ...
- kubernetes CRD开发指南
扩展kubernetes两个最常用最需要掌握的东西:自定义资源CRD 和 adminsion webhook, 本文教你如何十分钟掌握CRD开发. kubernetes允许用户自定义自己的资源对象,就 ...
- Django中自定义admin---Xadmin的实现
在Django框架中,自带一个后台管理页面admin,这个管理页面很全,但是,有些并不是我们需要的,所以我们可以根据admin的实现流程来自定义自己的需求,即根据admin的实现方式来实现自定制--X ...
- 简洁实用Socket框架DotNettySocket
目录 简介 产生背景 使用方式 TcpSocket WebSocket UdpSocket 结尾 简介 DotNettySocket是一个.NET跨平台Socket框架(支持.NET4.5+及.NET ...
- Java.基础 -------- 一个Java源文件中可以有很多类,但只能有一个类是public的
一个Java源文件中可以有很多类,但只能有一个类是public的 Java程序是从一个public类main函数开始执行的,只能有一个public是为了给类装载器提供方便,一个publi ...