1. 程式人生 > >有向圖傳遞閉包

有向圖傳遞閉包

題目 有向圖 class 時間 .com all 數據約束 htm 其中

目錄

  • 傳遞閉包的定義
  • Floyd warshall 傳遞閉包算法
    • Floyd warshall 代碼
    • 算法實現原理
    • Floyd warshall 傳遞閉包算法的實現
    • 時間復雜度
  • DFS 傳遞閉包算法
    • 算法分析
    • 代碼實現
  • 例題

有向圖的傳遞閉包是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 官網進行提交練習。

如有錯誤,懇請指正。

有向圖傳遞閉包