HDU1269迷宫城堡(强连通tarjan)

迷宫城堡

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

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大牛!*/
 


 

你可能感兴趣的:(HDU1269迷宫城堡(强连通tarjan))