对于给定的邻接矩阵 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),则为不连通的。