离散复习资料之一(Warshall算法)

我们先对R(n)进行解释一下,不然你们看不太懂。

就是R(n)表示,通过从 1...n 个点绕到到达所求点,注意原来的位置的点,发生改变的就是刚才的含义去解释。

 给一个例子解释一下。

 

其中的R(i)...R(N);(0<=N<=4)

初始的R(0)就是可达矩阵。

R(1)表示在R(0)的基础上面变化

R(1)表示在R(0)的基础上面变化

R(2)表示在R(1)的基础上面变化

R(3)表示在R(2)的基础上面变化

R(4)表示在R(3)的基础上面变化

 

关键:

R(0)表示直接相连的关系,可以到达就记为1,否则就记为0.

R(1)表示从该点通过1可以到达目标点的记为1,否则就记为0.(多出来的点的关系)

R(2)表示从该点通过1,2可以到达目标点到达的记为1.否则就记为0.(与R(1)相比,多出来的点的关系。)

R(3)与R(4)表示的意思同上。

Warshall算法思想:

      R(0)就只是有向图的邻接矩阵。

      R(1)包含可以用第一个顶点作为中间点的路径信息。

      R(n)说明可以用所有的顶点作为中间点寻找有向路径,所以R(n)就是我们要求的传递闭包,即可达矩阵。

      这个算法的中心是我们可以通过R(k-1)来计算R(k)的所有元素。

算法的步骤如下:

R(k) <- R(k-1)

for(k<-1;k<=n;k++)

   for(i<-1;i<=n;i++)

     for(j<-1;j<=n;j++)

          R(k)[i,j] = R(k-1)[i,j] or R(k-1)[i,k] and R(k-1)[k,j]

return  R(n)

 

通过上面的算法步骤,我们也可以知道,推出R(n),只要知道R(n-1)的关系矩阵从而推出R(n)。

每一点的计算关系都会遵循一个计算公式。

  “R(k)[i,j] = R(k-1)[i,j] or R(k-1)[i,k] and R(k-1)[k,j]”

从而程序代码也可以按照上面的计算关系进行计算,改变。

看一个代码改变一下求R(N),已知的是R(0)。

代码如下:
 

#include<iostream>  
#include<cstdio>  
  
using namespace std;  
  
int temp[5][5],temp1[5][5];  
  
void exchange(int sum,int k)  
{  
    for(int i=1;i<=sum;i++)  
    {  
        for(int j=1;j<=sum;j++)  
        {  
            temp[i][j] = temp1[i][j] or temp1[i][k] and temp1[k][j];  
        }  
    }  
      
    for(int i=1;i<=sum;i++)  
    {  
        for(int j=1;j<=sum;j++)  
        {  
            temp1[i][j] = temp[i][j];  
        }  
    }  
}  
  
int main()  
{  
    int sum;  
    cout<<"请输入你的矩阵边数:"<<endl;  
    cin>>sum;  
    cout<<"请输入各边的关系:"<<endl;  
    for(int i=1;i<=sum;i++)  
    {  
        for(int j=1;j<=sum;j++)  
        {  
            cin>>temp1[i][j];  
        }  
    }  
    exchange(sum,1);  
    cout<<"R(1)的传递闭包关系图如下:"<<endl;  
    for(int i=1;i<=sum;i++)  
    {  
        int ff=0;  
        for(int j=1;j<=sum;j++)  
        {  
            if(ff++!=0)  
              cout<<' ';  
            cout<<temp1[i][j];  
        }  
        cout<<endl;  
    }  
        exchange(sum,2);  
   cout<<"R(2)的传递闭包关系图如下:"<<endl;  
    for(int i=1;i<=sum;i++)  
    {  
        int ff=0;  
        for(int j=1;j<=sum;j++)  
        {  
            if(ff++!=0)  
              cout<<' ';  
            cout<<temp1[i][j];  
        }  
        cout<<endl;  
    }  
        exchange(sum,3);  
   cout<<"R(3)的传递闭包关系图如下:"<<endl;  
    for(int i=1;i<=sum;i++)  
    {  
        int ff=0;  
        for(int j=1;j<=sum;j++)  
        {  
            if(ff++!=0)  
              cout<<' ';  
            cout<<temp1[i][j];  
        }  
        cout<<endl;  
    }  
        exchange(sum,4);  
     cout<<"R(4)的传递闭包关系图如下:"<<endl;  
    for(int i=1;i<=sum;i++)  
    {  
        int ff=0;  
        for(int j=1;j<=sum;j++)  
        {  
            if(ff++!=0)  
              cout<<' ';  
            cout<<temp1[i][j];  
        }  
        cout<<endl;  
    }  
    return 0;  
}  

 

 

 

菜鸟的总结:在计算机里面计算矩阵的话,or 和 | 和 || ,and和 & 和 &&是一样的。想知道为什么吗? 哈哈,去看一下,位操作那一张呗!

 

运行结果如下:

请输入你的矩阵边数:
4
请输入各边的关系:
0 1 0 0
0 0 1 1
1 1 0 1
1 0 0 0
R(1)的传递闭包关系图如下:
0 1 0 0
0 0 1 1
1 1 0 1
1 1 0 0
R(2)的传递闭包关系图如下:
0 1 1 1
0 0 1 1
1 1 1 1
1 1 1 1
R(3)的传递闭包关系图如下:
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
R(4)的传递闭包关系图如下:
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1

--------------------------------
Process exited after 18.12 seconds with return value 0
请按任意键继续. . .

 

  • 15
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值