有向圖傳遞閉包



有向圖的傳遞閉包是Floyd warshall 算法的一種應用(主要參考算法導論)

傳遞閉包的定義

對於有向圖G(V,E)的傳遞閉包即是G(V,E),其中E{(i,j):圖G中包含一條由i到j的路徑}。

Floyd warshall 傳遞閉包算法

Floyd warshall 代碼

void floyd_warshall()
{
    int tmp;
    for(int k = 1; k <= n; ++k)
    {
        for(int i = 1; i <= n; ++i)
        {
            for(int j = 1; j <= n; ++j)
            {
                //松弛操作; 
                { 
                    tmp = mp[i][k] + mp[k][j];
                    if(tmp < mp[i][j])
                    {
                        mp[i][j] = tmp;
                    }
                }
            }
        }
    }
}

算法實現原理

由於我們只需要確定節點對(i,j)之間是存在i->j的路徑,所以,對於松弛操作可以有兩種優化方式,
(1)將所有節點對之間的存在的直接連通的邊權重設為1,不連通設為INF(無窮大)。然后運行該算法,如果mp[i][j] < n;則(i,j)之間存在一條簡單路徑。如果mp[i][j] = INF,則兩者之間不存在路徑。
(2)可以將松弛策略改為,mp[i][j] == 1|| (mp[i][k] ==1 && mp[k][j] == 1)也即是要么,i可以通過{1,2,3,,,k-1}中的部分節點到達j,要么i可以通過{1,2,3,,,k-1}中的部分節點到達j,可以參考對Floyd warshall 算法的分析鏈接

Floyd warshall 傳遞閉包算法的實現

void floyd_warshall()
{
	for(int k = 1; k <= n; ++k)
	{
		for(int i = 1; i <= n; ++i)
		{
			for(int j = 1; j <= n; ++j)
			{
				if(mp[i][j] == 1 || mp[i][k] == 1 && mp[k][j] == 1)
				{
					mp[i][j] = 1;
				}
			}
		}
	}
}

時間復雜度

容易知道時間復雜度為O(V^3);

DFS 傳遞閉包算法

算法分析

DFS時間復雜度為O(V+E);
使用對每個節點進行DFS,每次可以得出一個節點的可以到達的節點,可以求出有向圖的傳遞閉包,時間復雜度為V*O(V+E),即O(V*(V+E)); 
如果圖的邊數較少時,第二種算法更有效,可以根據題目的數據約束進行選擇。

代碼實現

int vis[N][N];//vis[i][j]表示i->j可達 
void dfs(int s)//普通的dfs算法
{
	int num = n;
	stack<int> st;
	st.push(s);
	vis[s][s] = 1;
	while(!st.empty())
	{
		int now = st.top();
		st.pop();
		int len = ed[now].size();
		for(int i = 0;i < len; ++i)
		{
			if(vis[s][ed[now][i]] == 0)
			{
				st.push(ed[now][i]);
				vis[s][ed[now][i]] = 1;
			}
		}
	}	
}			

例題

Cow Contest
通信網絡可以在CCF csp 官網進行提交練習。

如有錯誤,懇請指正。


免責聲明!

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



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