为了训练小希的方向感,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. ASP.NET Core Identity自定义数据库结构和完全使用Dapper而非EntityFramework Core

    前言 原本本节内容是不存在的,出于有几个人问到了我:我想使用ASP.NET Core Identity,但是我又不想使用默认生成的数据库表,想自定义一套,我想要使用ASP.NE Core Identi ...

  2. EasyUI combobox下拉列表实现搜索过滤(模糊匹配)

    项目中的某个下拉列表长达200多个项,这么巨大的数量一个一个找眼镜都得看花,于是就得整了个搜索功能.看网上别人帖子有只能前缀匹配的方案,但只能前缀匹配的话用起来也不是很方便.于是就记录一下模糊匹配的方 ...

  3. 转载 vue-awesome-swiper - 基于vue实现h5滑动翻页效果

    说到h5的翻页,很定第一时间想到的是swiper.但是我当时想到的却是,vue里边怎么用swiper?! 中国有句古话叫:天塌下来有个高的顶着. 在前端圈里,总有前仆后继的仁人志士相继挥洒着热汗(这里 ...

  4. JavaSE(二)标识符,关键字,数据类型

    一.标识符和关键字         1.具有特殊作用的分隔符:分号;.花括号{}.圆括号().空格.圆点 .          2.标识符规则:用于给程序中变量.类.方法命名的符号.       Ja ...

  5. [NUnit] discover test finished: 0 found issue

    %Temp%\VisualStudioTestExplorerExtensions & restart visual studio

  6. Android 使用 DiffUtil 处理 RecyclerView 数据更新问题

    背景 RecyclerView.Adapter#notifyDataSetChanged() 会每次刷新整个布局: 每次手动调用 RecyclerView.Adapter#notifyItemXx 系 ...

  7. Java——字符串

    1.不可变的String String对象是不可变的.String类中的每一个看起来会修改String值的方法,实际上都是创建了一个全新的String对象,以包含修改修改后的字符串内容. public ...

  8. (十五)c#Winform自定义控件-键盘(二)

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...

  9. AutoCAD.NET中添加图形对象的基本步骤与实例演示

    https://blog.csdn.net/u011170962/article/details/37755201 要创建一个图形对象,需要遵循下面的步骤:1.得到创建对象的图形数据库:2.在内存中创 ...

  10. 手撕ThreadPoolExecutor线程池源码

    这篇文章对ThreadPoolExecutor创建的线程池如何操作线程的生命周期通过源码的方式进行详细解析.通过对execute方法.addWorker方法.Worker类.runWorker方法.g ...