9.4 關係的閉包

#9.4 關係的閉包html

###閉包的定義: <font size=3>算法

關係R對於性質P的閉包,是加入最小數量的序偶,使得R剛好符合性質P所獲得的集合
R的閉包R<sub>1</sub>具備以下3個特色:
①. R<sub>1</sub> 包含 R
②. R<sub>1</sub>具備性質P
③. 若是R<sub>2</sub>具備性質P且R<sub>2</sub>包含R, 那麼R<sub>2</sub>包含R<sub>1</sub>數組

###就R的有向圖而言:閉包

  1. 找其自反閉包(reflexive closure)

添加循環/閉環flex

  1. 找其對稱閉包(symmetric closure)

沿相反方向添加弧線(箭頭)優化

  1. 找其傳遞閉包(transitive closure)

若是a到b連通, 那麼就添加從a到b的弧線(箭頭)url

<font color=#00ffff>自反閉包(reflexive closure)</font>
定理:R是定義在A上的關係,那麼R的自反閉包r(R) = R∪△
如何得到?.net

①. 在R的有向圖的全部頂點上添加閉環
②. 令R的鄰接矩陣的對角線上全爲13d

<font color=#00ffff>對稱閉包(symmetric closure)</font>code

定理①:R是定義在A上的關係,那麼R的對稱閉包s(R) = R∪R<sup>-1</sup>
NOTE: R<sup>-1</sup> = {(b, a) | (a, b) ∈ R}
NOTE: R<sup>-1</sup>的鄰接矩陣是R的鄰接矩陣的轉置,
即: M<sub>R</sub><sup>T</sup> = M<sub>R<sup>-1</sup></sub>

定理②:R是對稱的,當且僅當 R = R<sup>-1</sup>
NOTE:在對稱關係的有向圖中,用無向的邊來代替弧線(箭頭)

##路徑(Paths)

假設R爲定義在A上的關係,則R從a到b,長度爲n的路徑可表示爲以a爲起始點,b爲終點的一個有限序列π:
a, x<sub>1</sub>, x<sub>2</sub>, ..., x<sub>n-1</sub>, b;
其中,知足:a R x<sub>1</sub>, x<sub>1</sub> R x<sub>2</sub>, ..., x<sub>n-1</sub> R b

例:

####一些重要定義:

  • 環(cycle):

一條起始點和終點爲相同頂點的路徑稱爲:環(cycle)

  • R<sup>n</sup>:

x R<sup>n</sup> y表示,在R中存在一條或多條從x到y的路徑

  • 連通關係(connectivity relation) R<sup>*</sup>

R<sup>*</sup>包含的序偶對(a, b), 其中在R中至少存在一條從a到b的路徑

例:

####一些重要定理:

  1. 若是R是定義在A上的關係,那麼有:
    其中,⊙表示矩陣布爾乘法

證實:

  1. 當n>=2時,有:

證實:科學概括法(略)

##連通關係(The connectivity relation)

<font size=4 color=#00ffff>準備</font>

  • 路徑的合成

令:
π<sub>1</sub>: a, x<sub>1</sub>, x<sub>2</sub>, … , x<sub>n-1</sub>, b
π<sub>2</sub>: b, y<sub>1</sub>, y<sub>2</sub>, … , y<sub>m-1</sub>, c
則π<sub>1</sub>與π<sub>2</sub>合成後的路徑爲:
π<sub>2</sub> o π<sub>1</sub>:a, x<sub>1</sub>, x<sub>2</sub>, … , x<sub>n-1</sub>, b, y<sub>1</sub>, y<sub>2</sub>, … , y<sub>m-</sub>, c

NOTE THE ORDER!!!(注意順序)

  • 傳遞閉包(Transitive closure)

①. 關係R的傳遞閉包是包含R的最小的傳遞關係。

②. R是傳遞的, 當且僅當,對於任何的n,均有R<sup>n</sup> ⊆ R(結論來自9.1)

③. 若是傳遞閉包存在一條從x到y的路徑,那麼必定有從x直接到y的弧線(箭頭)

  • 傳遞閉包裏有用的一些結論:

①. If A ⊆ B and C ⊆ B, then (A∪C) ⊆ B.

②. If R ⊆ S and T ⊆ U then (RoT) ⊆ (SoU).

推論: If R ⊆ S then R<sup>n</sup> ⊆ S<sup>n</sup>

③. 若是R是傳遞的,那麼R<sup>n</sup>也是傳遞的 只需證實:(R<sup>n</sup>)<sup>2</sup> = (R<sup>2</sup>)<sup>n</sup> ⊂ R<sup>n</sup>

④. 若是對於j>k, 有R<sup>k</sup> = R<sup>j</sup>, 那麼對於某些n>=j, 有R<sup>j+m</sup> = R<sup>n</sup>
除了R<sup>j</sup>以外,咱們沒法獲得任何新的關係

  • 一個重要定理:

R爲定義在A上的一個關係,那麼R的閉包就等於R<sup>*</sup>

PROOF:咱們必須證實,R<sup>∞</sup>

1). 是一個傳遞關係
2). 包含R
3). 是包含R的最小的傳遞關係

Proof of Part 1):

假設(x, y)和(y, z)都在R<sup>*</sup>中,只需證(x, z)也在R<sup>*</sup>中
由R<sup>*</sup>定義知,必定存在m,n,使得(x, y)和(y, z)分別在R<sup>m</sup>和R<sup>n</sup>中
又由複合定理,知:(x, z) ∈ R<sup>n</sup>oR<sup>m</sup> = R<sup>m+n</sup> ⊆ R<sup>*</sup>
所以,R<sup>*</sup>是傳遞的

Proof of Part 2):

顯然.

Proof of Part 3):

###最重要的結論:

  • 若是集合A的維數 = n,即|A|=n, 那麼對於定義在A上的關係R,有:

  • 等價命題:對於k<=n<=m,有1)和2)同時成立

  • 1). R<sup>m</sup> ⊆ R<sup>k</sup>
  • 2). (a, b) ⊆ R<sup>m</sup> → (a, b) ⊆ R<sup>k</sup>

證實其實就是去掉環,此處略

##沃舍爾算法(Warshall’s Algorithm)

須要知道:內部頂點(Interior vertices)

###大體方法:

①. 將n個節點賦予順序爲{a<sub>1</sub>, a<sub>2</sub>,…, a<sub>n</sub>}, 並定義W<sub>k</sub> = [t<sub>ij</sub>]表示存在從第i個節點到第j個節點且僅經過內部節點{a<sub>1</sub>, a<sub>2</sub>,…, a<sub>k</sub>}這k個節點(這些節點可選可不選,但除此以外的節點都不能選)的路徑連通,並記爲「1」, 不然記爲「0」
②. W<sub>0</sub> = 初始鄰接矩陣M<sub>R</sub>
③. 利用W<sub>k-1</sub>來計算W<sub>k</sub>
④. 得連通矩陣M<sub>R<sup>*</sup></sub> = W<sub>n</sub>

###計算具體W<sub>k</sub>的作法:

對於W<sub>k</sub>中的t<sub>ab</sub>
①. 若是W<sub>k-1</sub>的s<sub>ab</sub> == ‘1’,即僅利用{a<sub>1</sub>, a<sub>2</sub>,…, a<sub>k-1</sub>}這k-1個點(固然包括第a和第b個頂點)就能使a連通到b,那麼W<sub>k</sub>的t<sub>ab</sub>直接 = ‘1’
②. 若是W<sub>k-1</sub>的s<sub>ab</sub> == ‘0’, 那麼要使僅用{a<sub>1</sub>, a<sub>2</sub>,…, a<sub>k</sub>}這n個點從a連通到b, 則:
只需存在一個m(1 <= m <= k-1),使得在W<sub>k-1</sub>中,有:s<sub>am</sub> == 「1」而且s<sub>mb</sub> == 「1」(在W<sub>k-1</sub>中,節點a到m連通,節點m到b連通, 那麼在W<sub>k</sub>中,節點a到b連通)

例:

核心代碼:

for(int k = 1; k <= N; k++)
{
	for(int i = 1; i <= N; i++)
	{
		for(int j = 1; j <= N; j++)
		{
			if(W[k-1][i][j]=='1')
			{
				W[k][i][j] = 1;
			}
			else if(W[k-1][i][k]=='1'&&W[k-1][k][j]=='1')
			{
				W[k][i][j] = 1;
			}
		}
	}	
}

時間複雜度:O(n^3)
空間複雜度:O(n^3)

其實因爲W[k]只與W[k-1]有關,能夠只用二維數組來表示W[k-1],而後更新W[k]的時候直接覆蓋到這個數組便可將空間複雜度壓縮成O(n^2)

實戰:Cow Contest

思路:只需求以這些牛組成有向圖的傳遞閉包(用連通矩陣表示),再判斷每一個節點的入度+出度是否等於n-1,來判斷每頭牛可否確認排名

AC代碼:

#include <stdio.h>

int main(void)
{
    int n, m, a, b; //n頭牛, m個關係
    scanf("%d %d",&n,&m);
    int W[n+1][n+1];
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++)
            W[i][j] = 0;
    for(int i = 1; i <= m; i++)
    {
        scanf("%d %d",&a,&b);
        W[a][b] = 1;  //初始賦值W[0]
    }
    //這裏即只需用一個二維數組表示W[k-1],而後將W[k]覆蓋到W[k-1]這個二維數組上,使得空間複雜度爲:O(n^2)
    for(int k = 1; k <= n; k++)
    {
        for(int i = 1; i <= n; i++)
        {
            for(int j = 1; j <= n; j++)
            {
                //if(W[i][j]==1) // 表明第一種狀況,徹底能夠省去
                //  W[i][j] = 1;
                if(W[i][j]==0)  //表明第二種狀況
                {
                    if(W[i][k]==1&&W[k][j]==1)
                        W[i][j] = 1;
                }
            }
        }
    }
    int sumdu = 0, ans = 0;
    for(int i = 1; i <= n; i++)  //判斷每一個點的入度和出度之和是否爲n-1
    {
        sumdu = 0;
        for(int j = 1; j <= n; j++)
        {
            if(W[i][j]==1||W[j][i]==1)
                sumdu++;
        }
        if(sumdu==n-1)
            ans++;
    }
    printf("%d\n",ans);
    return 0;
}

##OTHERS

###解決最短路徑問題有幾個經常使用的算法:

  • ①. dijkstra算法,最經典的單源最短路徑算法
  • ②. bellman-ford算法,容許負權邊的單源最短路徑算法
  • ③. spfa,實際上是bellman-ford+隊列優化,其實和bfs的關係更密一點
  • ④. floyd算法,經典的多源最短路徑算法

而Warshall算法和flody算法最具殊途同歸之妙:

flody算法:<font color=#00ffff>用W<sub>k</sub>的t<sub>ab</sub>表示點a到點b只用{a<sub>1</sub>, a<sub>2</sub>,…, a<sub>k</sub>}這k個點和a與b所能達到的最短路徑值,和Warshall算法同樣,用W[k-1]來計算W[k],而W<sub>n</sub>即爲全部兩點之間(即多源)最短路徑的答案</font>

  • flody算法是用來求圖的多源最短路徑的算法,複雜度也爲O(n^3)
  • 將連通的邊權定爲有限值(如1),不連通的邊權定爲∞,即可以用flody算法求全部點的連通性(如i, j兩個節點的最短路徑爲有限值即連通)
  • Warshall算法和flody算法都能用動態規劃的想法來理解:動態規劃深入理解flody
  • 爲何 Dijkstra 不能提出 floyd 算法?由於他的名字是 ijk 而不是 kij
相關文章
相關標籤/搜索