目錄
有向圖的傳遞閉包是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 官網進行提交練習。
如有錯誤,懇請指正。