1. 程式人生 > >HDU1269 強連通分量-tarjan演算法

HDU1269 強連通分量-tarjan演算法

題意就是在給定一個圖的情況下,問這個單向圖是不是強連通圖。

強連通圖的意思就是圖中任何一個點都可以到達另一個點。

分析:這道題是tarjan演算法求強連通分量的模板題,對於tarjan演算法求連通分量的方法大致上是給每一個點標兩個號,一個是自己是第幾個被搜尋到i,也叫時間標號(程式碼中用dfn【i】來表示第i個點的標號),另一個是這個點的子樹中所能搜到的最小的時間標號(程式碼中用low【i】)表示,如果時間標號==low【i】那麼表示形成了一個聯通分量,具體的或者更加詳細的參考https://www.cnblogs.com/shadowland/p/5872257.html

再來說本題:要想證明一個圖是連通圖,則只需要證明整個圖只有一個連通分量即可;

程式碼:

#include<cstdio>
#include<stack>
#include<cstring>
#include<algorithm>

using namespace std;

const int maxn = 1e4 + 10;
const int maxm = 1e5 + 10;
int cnt = 0;
int ans = 0;
int n, m;
int head[maxn], dfn[maxn], low[maxn];
bool vis[maxn];
stack<int>iron;
struct Edge
{
		int from,to, next;
}edge[maxm];

void addedge(int u, int v)
{
		edge[cnt].from = u, edge[cnt].to = v;
		edge[cnt].next = head[u];
		head[u] = cnt++;
}
void ini()
{
		memset(head,-1,sizeof (head));
		memset(dfn, 0, sizeof(dfn));
		memset(vis, false, sizeof(vis));
		memset(low, 0, sizeof(low));
		cnt = ans = 0;
}

void dfs(int x)
{
		dfn[x] = low[x] = ++cnt;
		iron.push(x);
		vis[x] = 1;
		for (int i = head[x]; ~i; i = edge[i].next)
		{
				int j = edge[i].to;
				if (!dfn[j])
						dfs(j);
				low[x] = min(low[x], low[j]);
		}
		if (low[x] == dfn[x])
		{
				++ans;
				while (!iron.empty())
				{
						int t = iron.top();
						vis[t] = 0;
						iron.pop();
						if (t == x)
								break;
				}
		}
}

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

int main()
{
		while (scanf("%d %d", &n, &m) && n || m)
		{
				int u, v;
				ini();
				for (int i = 0; i < m; i++)
				{
						scanf("%d %d", &u, &v);
						addedge(u, v);
				}
				cnt = 0;
				ans = 0;
				tarjin();
				if (ans == 1)
						printf("Yes\n");
				else
						printf("No\n");
		}
		//system("pause");
		return 0;
}