[tarjan][hdu 1269]



[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

#include <cstdio>
#include <cstring>
#include <iostream>
#include <stack>
using namespace std;
const int maxn=10000+10;

int n,m,idx,k=1,cnt;
int head[maxn];
int dfn[maxn],low[maxn];
int ins[maxn],belong[maxn];
stack <int >s;
struct edge
{
    int v,next;
}e[maxn*10];

void adde(int u,int v)
{
     e[k].v=v;
     e[k].next=head[u];
     head[u]=k++;
}

void tarjan(int u)
{
     int v;
     dfn[u]=low[u]=++idx;
     s.push(u);
     ins[u]=1;
     for(int i=head[u];i!=-1;i=e[i].next)
     {
         v=e[i].v;
         if(!dfn[v])
         {
             tarjan(v);
             low[u]=min(low[u],low[v]);
         }
         else if(ins[v])low[u]=min(low[u],dfn[v]);
     }
     if(dfn[u]==low[u])
     {
         cnt++;
         while(u!=v)
         {
             v=s.top();
             s.pop();
             ins[v]=0;
             belong[v]=cnt;
         }
     }
}

void work()
{
     int a,b;
     while(1)
     {
        memset(head,-1,sizeof(head));
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(dfn));
        memset(ins,0,sizeof(dfn));
        memset(belong,0,sizeof(dfn));
        idx=0,cnt=0;
        scanf("%d%d",&n,&m);
        if(n==0&&m==0)break;
        for(int i=1;i<=m;i++)
        {
           scanf("%d%d",&a,&b);
           adde(a,b);
        }
        for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);
        if(cnt>1)printf("No\n");
        else printf("Yes\n");
     }
}

int main()
{
    work();
    return 0;
}


你可能感兴趣的:(Tarjan)