迷宫城堡
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 5345 Accepted Submission(s): 2386
Problem Description
为了训练小希的方向感,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
1 2
2 3
3 1
3 3
1 2
2 3
3 2
0 0
Sample Output
Yes
No
/********************************************************************************
* 算法原理:Tarjan算法是基于对图深度优先搜索的算法,
* 每个强连通分量为搜索树中的一棵子树。搜索时,把当前搜索树中未处理的节点加入一个堆栈,
* 回溯时可以判断栈顶到栈中的节点是否为一个强连通分量。
* 定义:定义DFN(u)为节点u搜索的次序编号(时间戳),Low(u)为u或u的子树能够追溯到
* 的最早的栈中节点的次序号。
* 结论:当DFN(u)=Low(u)时,以u为根的搜索子树上所有节点是一个强连通分量。
* Low(u)=Min
* {
* DFN(u),
* Low(v),(u,v)为树枝边,u为v的父节点
* DFN(v),(u,v)为指向栈中节点的后向边(非横叉边)
* }
*
* 备注:tarjan模板题
* Problem:HDU1269迷宫城堡
* author:crazy_石头
* date: 2013/09/07
*********************************************************************************/
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define A system("pause")
using namespace std;
const int maxn=10000+5;
struct Node
{
int v,next;
}edge[maxn*10];
int dfn[maxn],low[maxn];
bool instack[maxn];
int stack[maxn];
int head[maxn];
int top,Bcnt,index;
int cnt;
int n,m;
void addedge(int u,int v)
{
edge[cnt].v=v;
edge[cnt].next=head[u];
head[u]=cnt++;
}
void tarjan(int u)
{
int v;
dfn[u]=low[u]=++index;
instack[u]=true;
stack[++top]=u;
for(int i=head[u];~i;i=edge[i].next)//枚举每条边;
{
v=edge[i].v;//找到其邻接点;
if(!dfn[v])//该点未访问过,则访问该点;
{
tarjan(v);
low[u]=min(low[u],low[v]);//树边;
}
else if(instack[u])
{
low[u]=min(dfn[v],low[u]);//后向边;
}
}
if(dfn[u]==low[u])
{
Bcnt++;
do
{
v=stack[top--];
instack[v]=false;
}while(v!=u);
}
}
void solve()
{
int i;
top=index=Bcnt=0;
memset(instack,0,sizeof(instack));
memset(dfn,0,sizeof(dfn));
for(i=1;i<=n;i++)
{
if(!dfn[i])
tarjan(i);
}
if(Bcnt==1)
puts("Yes");
else
puts("No");
}
int main()
{
while(scanf("%d%d%*c",&n,&m)!=EOF)
{
if(n==0&&m==0)
break;
cnt=0;
memset(head,-1,sizeof(head));
for(int i=0;i<m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
addedge(a,b);
}
solve();
}
return 0;
}
/*PS:刚开始一直样例WA是因为tarjan(i)写成了tarjan[i],最近老是犯二。。。。感谢byvoid大牛!*/
本文探讨了如何使用深度优先搜索和Tarjan算法解决迷宫城堡问题,即确定城堡中任意两个房间是否都能互相到达。通过构建有向图,利用Tarjan算法来识别强连通分量,从而判断整个城堡是否连通。
1万+

被折叠的 条评论
为什么被折叠?



