HDU 1269(Tarjan模板)

8 篇文章 0 订阅
6 篇文章 0 订阅

HDU - 1269
Time Limit: 1000MS Memory Limit: 32768KB 64bit IO Format: %I64d & %I64u

            

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
 

Hint

Source

HDU 2006-4 Programming Contest

题意: 求所有房间是否连通,即判断是否只有一个强连通分量。
Tarjan算法= =
AC代码 :
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxn 10000+10
#define maxm 100000+10
int n, m;
struct Edge
{
   int to,next;
}edge[maxm];
int head[maxn],tot;
int low[maxn],dfn[maxn],Stack[maxn],belong[maxn];
int index,top;
int scc; //强连通分量数量
bool instack[maxn];
void addedge(int u,int v)
{
  edge[tot].to = v;
  edge[tot].next = head[u];
  head[u] = tot++;
}
void tarjan(int u)
{
  int v;
  low[u] = dfn[u] = ++index;
  Stack[top++] = u;
  instack[u] = true;
  for(int i = head[u]; i != -1; i = edge[i].next)
  {
	v = edge[i].to;
    if(!dfn[v])
	{
	  tarjan(v);
	  if(low[v] < low[u])
	  low[u] = low[v];
	}
	else
	{
	  if(instack[v] && dfn[v] < low[u])
	  {
	    low[u] = dfn[v];
	  }
    }
  }
  if(dfn[u] == low[u])
  {
   scc ++;
   do
   {
     v= Stack[--top];
     instack[v] = false;
     belong[v] = scc;
   }
   while(v != u);
  }
}
void solve()
{
  memset(low, 0, sizeof(low));
  memset(dfn, 0, sizeof(dfn));
  memset(instack, false, sizeof(instack));
  scc = tot = index = 0;
  for(int i = 1;i <= n;i ++)
  {
    if(dfn[i] == 0)
	tarjan(i);
  }
}
int main()
{
    while(scanf("%d%d", &n, &m) != EOF)
	{
	  int x, y;
	  memset(head, -1, sizeof(head));
	  if(n+m == 0) break;
	  while(m --)
	  {
	   scanf("%d%d", &x, &y);
	   addedge(x, y);
	  }
      solve();
      if(scc == 1)
	  printf("Yes\n");
	  else
	  printf("No\n");
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值