离散实验八 判别图的连通性 (给定 n 个结点的有向图的邻接矩阵,可判断该图是否为强连通的,单向连通 的,或弱连通的)

对于给定的邻接矩阵 A,我们可以用前面给出的可达矩阵 Warshall 算法求 出 A 所表示的图的可达矩阵 P。对于可达矩阵 P 来说,如果 P 的所有元素均为 1, 则所给的有向图是强连通的;对于 P 的所有元素(除主对角线元素外)Pij 来说, 均有:Pij+Pji>0,则所给有向图是单向连通的。当所给有向图既不是强连通的, 又不是单向连通的时候,我们改造邻接矩阵为:对于矩阵 A 中所有的元素(除主 对角线的元素外)aij,若 aij=1 或 aji=1,则 1 Þ aij 且 1 Þ aji。对于这样改造之后 所得到的新的矩阵 A’(A’相当于原有向图忽略方向之后所得到的无向图的邻 接矩阵),再用前面所述的方法进行判断,当 P’的所有元素(除主对角线的元 素外)均为 1 时,原有向图是弱连通图;否则,原有向图是不连通的。 

附上运行截图:

附上代码:

 

#include<iostream>
#include<cstring> 
using namespace std;
int main()
{
    
    int a[100][100];
    int b[100][100];
    int c[100][100];
    int d[100][100]; 
    int e[100][100];
    int sum[100][100];
    int sum2[100][100];
    int count=0,flag1=2,flag2=2,flag3=2;
    int n;
    
    cout<<"请输入邻接矩阵阶数:"<<endl;
    cin>>count; 
    n=count;
    cout<<"请输入邻接矩阵:"<<endl;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
    {
        cin>>a[i][j];
     } 
    }
    
    
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
    {
        sum[i][j]=a[i][j];
     } 
    }
    
    
    for(int i=0;i<n;i++)
    for(int j=0;j<n;j++)
    for(int z=0;z<n;z++)
    {
        b[i][j]+=a[i][z]*a[z][j];
    }
    
    count=count-2;
    
    for(int i=0;i<n;i++)
    for(int j=0;j<n;j++)
    {
        sum[i][j]=sum[i][j]+b[i][j];
    }
    
//处理成可达矩阵    
    while(count!=0)
    {

    for(int i=0;i<n;i++)
    for(int j=0;j<n;j++)
    for(int z=0;z<n;z++)
    {
        c[i][j]+=b[i][z]*a[z][j];
    } 
    count=count-1;
    
    for(int i=0;i<n;i++)
    for(int j=0;j<n;j++)
    {
        sum[i][j]=sum[i][j]+c[i][j];
    }
    
    memcpy(b,c,sizeof(c));
    memset(c,0,sizeof(c));
    }
    
    

    
    for(int i=0;i<n;i++)
    for(int j=0;j<n;j++)
    {
        if(sum[i][j]!=0)
        sum[i][j]=1;         //此时矩阵为可达矩阵 
    }
    
    for(int i=0;i<n;i++)
    for(int j=0;j<n;j++)
    {
        if(sum[i][j]!=1)
        flag1=0;     //不是强连通 
     } 
     
     if(flag1!=0)
     flag1=1;
     
     
     for(int i=0;i<n;i++)
     for(int j=0;j<n;j++)
    {
        if(i!=j)
        {
        if(sum[i][j]+sum[j][i]<=0)
        flag2=0;        //不是单向连通 
        }         
    } 
    
    if(flag2!=0)
    flag2=1;
    
    
    
    
    //判断弱连通情况 
    
    
    
    
    if(flag1==0&&flag2==0)
    {
        for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        {
            if(i!=j)
            {
                if(a[i][j]==1||a[j][i]==1)
                {
                    a[i][j]=a[j][i]=1;      //新的邻接矩阵 
                } 
            }
        } 
        
        for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        {
            sum2[i][j]=a[i][j];
        }
        
    for(int i=0;i<n;i++)
    for(int j=0;j<n;j++)
    for(int z=0;z<n;z++)
    {
        d[i][j]+=a[i][z]*a[z][j];
    }
    
        for(int i=0;i<n;i++)
    for(int j=0;j<n;j++)
    {
        sum2[i][j]=sum2[i][j]+d[i][j];
    }
    
    count=n;
    count=count-2;
    
    
//处理成可达矩阵    
    while(count!=0)
    {

    for(int i=0;i<n;i++)
    for(int j=0;j<n;j++)
    for(int z=0;z<n;z++)
    {
        e[i][j]+=d[i][z]*a[z][j];
    } 
    count=count-1;
    
    for(int i=0;i<n;i++)
    for(int j=0;j<n;j++)
    {
        sum2[i][j]=sum2[i][j]+e[i][j];
    }
    
    memcpy(d,e,sizeof(e));
    memset(e,0,sizeof(e));
    }
    
    

    
    for(int i=0;i<n;i++)
    for(int j=0;j<n;j++)
    {
        if(sum2[i][j]!=0)
        sum2[i][j]=1;         //此时矩阵为可达矩阵 
    }
    
    
    for(int i=0;i<n;i++)
    for(int j=0;j<n;j++) 
        {
            if(i!=j)
            {
                if(sum2[i][j]!=1)
                flag3=0;     //不是弱连通 
            }
        }
        
        if(flag3!=0)
        flag3=1;
        
    }
    
    
    if(flag1==1)
    cout<<"该图是强连通的";
    else if(flag1==0&&flag2==1)
    cout<<"该图是单向连通的";
    else if(flag1==0&&flag2==0&&flag3==1) 
    cout<<"该图是弱连通的";
    else if(flag1==0&&flag2==0&&flag3==0)
    cout<<"该图是不连通的";
                                                                
    
    return 0;
}

                                                     总结:

先输入一个邻接矩阵,然后分别求出其1次方,2次方....n次方(n=邻接矩阵的阶数)。然后将这些相加,凡是大于0的元素,使其成为1,得到可达矩阵。对可达矩阵进行相关判断。

如果可达矩阵所有元素都为1,flag1=1,则其邻接矩阵为强连通的。如果除主对角线元素外,对称的两元素相加大于0,flag2=1,则为单向连通的。如果两者都不是,flag1=0&&flag2=0,则对邻接矩阵进行改造,如果对称的两元素中有一个是1,则使对称的两个元素都为1,处理完之后在进行上述操作,使新的邻接矩阵成为可达矩阵,如果除主对角线的元素外都为1,则为弱连通的(flag1=0,&&flag2=0&&flag3=1)。如果(flag1=0&&flag2=0&&flag3=0),则为不连通的。

  • 8
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值