算法之判斷一個圖是否有環


在一些經典算法中,經常需要判斷一些圖是否具有環路,比如拓撲排序,需要在最初判斷該圖是否有環路,如有有環路,則無法找到最長的一條線,比如dijkstra算法,每找到一條最短的邊,都要判斷找到的邊和現有的樹是否已經構成了環路。

因此,在這篇博客,我們重點來說一個判斷圖是否有環的算法。

首先我們介紹一個對於無向圖和有向圖通用的算法,先講算法思路:

  1.統計各個圖中各個點的入度數(能夠到達這個點的點的數量)。

  2.然后找出入度數為0的點(無向圖找入度數為1的點)。

  3.刪除入度數為0的點,將其邊也刪除。

  4.重復2,直到所有點入度都為0,則為無環圖,如果找不到入度為0的點,則為有環圖。

該算法的精髓在於對於一個環路(以有向圖為例),1->2,2->3,3->1,你會發現找不到一個入度為0的點,因此這個方法是可行的。

對於無向圖和有向圖來說,這個算法是通用的。在這我只寫了對於有向圖的判斷的算法,具體的實現代碼如下:

#include<stdio.h>
using namespace std;
int graph[100][100];//用來存儲圖的數組
bool isVisited[100];//判斷這個點是否已經刪除
int main()
{
	int n,e;
	while (scanf("%d",&n)!=EOF&&n!=0)//獲取點數
	{
		for(int i = 0;i<100;i++)
		{
			isVisited[i] = false;
			for(int j = 0 ;j<100;j++)
			{
				graph[i][j] = -1;//初始化數據,所有的邊都為-1,代表這兩個點之間不能聯通
			}
		}
		scanf("%d",&e);//獲取邊數
		for(int i = 0 ;i<e;i++)//構建圖
		{
			int a,b,c;
			scanf("%d %d %d",&a,&b,&c);
			graph[a-1][b-1] = c;
		}
		int isResult = true;
		for(int i = 0 ;i<n;i++)//進行n次循環,每次循環刪除一個入度為0的點,所以進行n次循環
		{
			for(int j = 0;j<n;j++)//遍歷所有的點,找入度為0的點
			{
				if(!isVisited[j])//判斷該點是否刪除
				{
					bool isCanVisited = true;//輔助變量,判斷這個點是否入度為0
					for(int k = 0;k<n ;k++)
					{
						if(graph[k][j]!=-1)
						{
							isCanVisited = false;//如果存在能夠訪問這個點的邊,則該點入度不為0
						}
					}
					if(isCanVisited)//如果該點入度為0,則下邊是刪除該點和刪除其相鄰邊
					{
						for(int k = 0 ;k<n;k++)
						{
							graph[j][k] = -1;//刪除相鄰邊,即將值變為-1
						}
						isVisited[j] = true;//刪除該點
					}
				}
			}
			isResult = true;
			for(int j = 0 ;j<n;j++)//進行循環判斷當前多有點是否已經全部刪除,如果全部刪除,如果全部刪除則跳出,否則繼續循環
			{
				if(!isVisited[j])
				{
					isResult = false;
				}
			}
			if(isResult)
				break;
		}
		isResult = true;
		for(int i = 0 ;i<n;i++)//在所有點遍歷后,則通過這個循環來判斷是否所有點都已經刪除,如果全部刪除,則為無環圖,否則為有環圖
		{
			if(!isVisited[i])
				isResult = false;
		}
		if(isResult)
			printf("無環");
		if(!isResult)
			printf("有環");
	}
	return 0;

}

實驗數據(第一行輸入n,e,n代表的是點數,e代表的是邊數,接下來e行代表具體的邊和其權值(權值暫時不用理會,是后續拓撲排序所有,因此當前暫時都為1)):

5 4
1 2 1
1 3 1
2 3 1
4 5 1

5 4
1 2 1
2 1 1
2 3 1
4 5 1

實驗結果:

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM