WARSHALL算法计算传递闭包

时间:2021-06-14 11:27:14

    考虑n+1个矩阵的序列M0,M1,……,Mn,将矩阵Mk的第i行记作Mk[i,j].

    对于k=0,1,……,n,Mk[i,j]=1当且仅当在R的关系图中存在一条从xi到xj路径,并且这条路径除了端点外中间只经过{x1,x2,……,xk}中的结点。WARSHALL算法从M0开始,顺序计算M1,M2,……,直到Mn为止。

    我们知道,对于关系R对应的关系矩阵M来讲,其传递闭包R(t)对应的矩阵MT中,MT[i,j] = 1,当且仅当M[i,j] = 1或M[i,k] = M[k,j] = 1.

算法Warshall

输入:M(R的关系矩阵)

输出:MT(t(R)的关系矩阵)

1.MT <- M 

2.for k <- 1 to n do

3.    for i <- 1 to n do

4.        for j <- 1 to n do

5            MT[i,j] <- MT[i,j] + MT[i,k] * MT[k,j](此处的“+”和“*”都是逻辑加和逻辑乘)

具体代码如下:

#include<stdio.h>
int main(void){
        //get |A|
        int n;
        printf("plz input |A|.\n");
        scanf("%d",&n);
        //input R[n][n]
        printf("plz input R.\n");
        int R[n][n] = {0};
        for(int i1 = 0; i1 <= n-1; i1++)
            for(int j1 = 0; j1 <= n-1; j1++)
                scanf("%d",&R[i1][j1]);
        //Warshall
        for(int i2 = 0; i2 <= n-1; i2++)
            for(int j2 = 0; j2 <= n-1; j2++)
        {
                if(R[j2][i2] != 0)
                {
                   for(int k = 0; k <= n-1; k++)
                        R[j2][k] |= R[i2][k];
                }
        }
        //output t(R)
        printf("t(R):\n");
        for(int i3 = 0; i3 <= n-1; i3++)
        {
           {
                for(int j3 = 0; j3 <= n-1; j3++)
                    printf("%d ",R[i3][j3]);
           }
           printf("\n");
        }

}