poj-1236-一起學習強連通分量

來源:互聯網
上載者:User
文章目錄
  • 代碼:

題目不是很好理解,簡單說一下

就是有一個有向圖,第一問求至少要複製幾次軟體,才能保證每個地方都有,實際上就是求入度為0的,也就是走不到的。第二問求至少添加幾個擴充,也即是添加幾條邊,讓無論從那個地方,都能讓任何地方得到軟體。也就是添加幾條邊,能讓整個圖強連通。

 

強連通分量演算法1---kosaraju最好理解的兩次dfs。

步驟概要:

1. DFS有向圖G,並以後根序記錄節點

2. 把存在於記錄集中且最後訪問節點作為起點,DFS反圖GT,並以先根序把節點從屬記錄中剔除;

3. 若此次不能DFS反圖GT所有節點,則重複步驟2,直到所有節點都被剔除出記錄;每次剔除掉的節點集即為原有向圖G的一個強連通分量

 

簡要證明:

1. 第一次DFS有向圖G時,最後記錄下的節點必為最後一棵產生樹的根節點。
證明:假設最後記錄下節點不是樹根,則必存在一節點為樹根,且樹根節點必為此節點祖先;而由後根序訪問可知祖先節點比此節點更晚訪問,矛盾;原命題成立

2. 第一次DFS的產生森林中,取兩節點A、B,滿足:B比A更晚記錄下,且B不是A的祖先(即在第一次DFS中,A、B處於不同的產生樹中);則在第二次DFS的產生森林中,B不是A的祖先,且A也不是B的祖先(即在第二次DFS中,A、B處於不同的產生樹中)。

證明:假設在第二次DFS的產生森林中,B是A的祖先,則反圖GT中存在B到A路徑,即第一次DFS產生森林中,A是B的祖先,則A必比B更晚記錄下,矛盾;假設在第二次DFS的產生森林中,A是B的祖先,則反圖GT中存在A到B路徑,即第一次DFS產生森林中,B是A的祖先,矛盾;原命題成立

3. 按上述步驟求出的必為強連通分量
證明:首先,證明2保證了第二次DFS中的每一棵樹都是第一次DFS中的某棵樹或某棵樹的子樹。其次,對於第二次DFS中的每棵樹,第一次DFS保證了從根到其子孫的連通性,第二次DFS保證了根到子孫的反向連通性(即子孫到根的連通性);由此,此樹中的每個節點都通過其根相互連通。

代碼:
#include <stdio.h>#include <stdlib.h>#include <string.h>#define nMax 110int map[nMax][nMax],mapT[nMax][nMax];int belong[nMax];int order[nMax];bool vist[nMax];int n,index,cnt;int indegree[nMax],outdegree[nMax];void firstDfs(int u)//第一次dfs,求出各點被搜尋時的時間戳記{vist[u] = true;for (int i = 1; i <= n; ++ i){if (map[u][i] && !vist[i]){firstDfs(i);}}order[++ index] = u;//記錄每點被搜尋時的時間戳記//printf("%d\n", u);}void secondDfs(int u)//第二次dfs,找到每個強連通分量{vist[u] = true;belong[u] = cnt;//記錄u點屬於哪個強連通分量cntfor (int i = 1; i <= n; ++ i){if (!vist[i] && mapT[u][i]){secondDfs(i);}}}void kosaraju(){index = 0;cnt = 0;memset(vist, false, sizeof(vist));memset(order, 0, sizeof(order));for (int i = 1; i <= n; ++ i){if (!vist[i]){firstDfs(i);//dfs求各點時間戳記}}memset(vist, false, sizeof(vist));for (int i = n; i >= 1; -- i)//倒著搜尋找到各個強連通分量{if (!vist[order[i]]){cnt ++;//強連通分量的個數secondDfs(order[i]);}}}void output(){int inNum = 0,outNum = 0;memset(indegree, 0, sizeof(indegree));memset(outdegree, 0, sizeof(outdegree));for (int i = 1; i <= n; ++ i)//求強連通分量的出度和入度{for (int j = 1; j <= n; ++ j){if (map[i][j] && belong[i] != belong[j]){indegree[belong[j]] ++;outdegree[belong[i]] ++;}}}for (int i = 1; i <= cnt; ++ i)//求出出度和入度為0的點的個數{if (!indegree[i]){inNum ++;}if (!outdegree[i]){outNum ++;}}if (cnt == 1)//如果這個圖強連通{printf("1\n0\n");}else//否則printf("%d\n%d\n",inNum, inNum > outNum ? inNum : outNum);}int main(){while (scanf("%d", &n) != EOF){memset(map, 0, sizeof(map));memset(mapT, 0, sizeof(mapT));for (int i = 1; i <= n; ++ i){int v;while (scanf("%d", &v) && v){map[i][v] = 1;//正向圖鄰接矩陣mapT[v][i] = 1;//逆向圖鄰接矩陣}}kosaraju();//kosaraju演算法output();}return 0;}

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.