1. 程式人生 > >HDU1269-Tarjan演算法

HDU1269-Tarjan演算法

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

 

 

 

AC_CODE: 

#include <bits/stdc++.h>
#define N 11000
#define M 110000
using namespace std;
struct EDG
{
	int u, v, nxt;
}edg[M];
int head[N], dfn[N], low[N], v[N], q[N], cnt, scnt, top, n, m, blong[N];
void init()
{
	memset(head, 0, sizeof(head));
	memset(dfn, 0, sizeof(dfn));
	cnt = top = scnt = 0;
}
void tarjan(int u)
{
	int t;
	dfn[u] = low[u] = m++;
	v[u] = 1;
	q[top++] = u;
	for (int i = head[u]; i; i = edg[i].nxt)
	{
		int c = edg[i].v;
		if (!dfn[c])
		{
			tarjan(c);
		}
		low[u] = min(low[u], low[c]);

	}
	if (dfn[u] == low[u])
	{
		scnt++;
		do
		{
			t = q[--top];
			v[t] = 0;
			blong[t] = scnt;
		} while (t != u);
	}
}

void solve()
{
	for (int i = 1; i <= n; i++)
		if (!dfn[i]) tarjan(i);
}

int main()
{
	while (~scanf("%d%d", &n, &m) && (n || m))
	{
		init();
		for (int i = 1; i <= m; i++)
		{
			int u, v;
			scanf("%d%d", &u, &v);
			edg[i] = { u,v,head[u]};
			head[u] = i;
		}
		solve();
		cout << (scnt == 1 ? "Yes" : "No") << endl;
	}
}