这是在第一个程序之后写的一个精简版:
int a[5][5]={{0,0,0,0,0},{0,0,1,1,0},{1,0,0,1,0},{0,0,1,0,1},{1,0,0,0,0}};
int b[5][5]={{1,0,0,0,0},{0,1,0,0,0},{0,0,1,0,0},{0,0,0,1,0},{0,0,0,0,1}};
int c[5][5]={0};//每次都乘以C[][]
int e[5][5]={0};//存放(A+I)的n次方的结果,用于与(A+I)的n+1次方比较
int d[5][5]={0};
//函数声明
void f1(); //求(a+i)的n次方
int f2(int e[][5],int d[][5]);//判断两个矩阵是否相等
void f3(int a[][5],int b[][5]);//一个矩阵的值赋给另外一个矩阵存起来
void f4();//求可达集合和先行集合
void f5();//层级数
void f6(int m);//删除其中相等的元素或集合
void main()
{
for(int i=0;i<5;i++)
for(int j=0;j<5;j++)
c[i][j]=a[i][j]>=b[i][j] ? a[i][j] : b[i][j];
f3(e,c);
printf("输出原始邻接矩阵和单位矩阵的布尔加法/n");
for(i=0;i<5;i++)
{
for(int j=0;j<5;j++)
printf("%d ",e[i][j]);
printf("/n");
}
f3(d,c);
f1();
while(f2(e,d)!=1)//如果两个矩阵不相等,则继续调用f1();让d[][]*c[][];直到他们相等,则跳出循环
f1();
printf("输出可达矩阵:/n");
for(i=0;i<5;i++)
{
for(int j=0;j<5;j++)
printf("%d ",d[i][j]);
printf("/n");
}
f4();
f5();
}
void f1() //求(a+i)的n次方
{
f3(e,d);//此处先把上次乘出的值存放在e[][]中,用于下次比较
for(int i=0;i<5;i++)
for(int j=0;j<5;j++)
for(int k=0;k<5;k++)
{
int t=e[i][k]*c[k][j];
d[i][j]=d[i][j]>=t ? d[i][j] : t;
}
}
int f2(int e[][5],int d[][5])//判断两个矩阵是否相等
{
for(int i=0;i<5;i++)
for(int j=0;j<5;j++)
if(e[i][j]!=d[i][j])
{
return 0;
break;
}
return 1;
}
void f3(int a[][5],int b[][5])//一个矩阵的值赋给另外一个矩阵存起来
{
for(int i=0;i<5;i++)
for(int j=0;j<5;j++)
a[i][j]=b[i][j];
}
//a[][]用来存放可达集合 b[][]用来存放先行集合 c[][]用来存放可达集合与先行集合的交集
void f4()//求可达集合和先行集合
{
for(int i=0;i<5;i++)//求可达集合,对于行来说,就是可达集合
for(int j=0;j<5;j++)
if(d[i][j]==1)
a[i][j]=j+1;
for(int j=0;j<5;j++)//求先行集合,对于列来说,就是先行集合
for(int i=0;i<5;i++)
if(d[i][j]==1)
b[i][j]=i+1;
for(i=0;i<5;i++)//求转置矩阵
{
int t;
for(int j=0;j<i;j++)
{
t=b[i][j];
b[i][j]=b[j][i];
b[j][i]=t;
}
}
for(i=0;i<5;i++)
for(int j=0;j<5;j++)
c[i][j]=0;//将c[][]矩阵清零,用来存放可达集合与先行集合的交集
for(i=0;i<5;i++)
for(int j=0;j<5;j++)
{
if(a[i][j]==b[i][j])
{
c[i][j]=a[i][j];
}
}
printf("输出 可达集合 先行集合 可达集合与先行集合的交集/n");
for(i=0;i<5;i++)
{
printf("第%d 行: ",i+1);
for(int j=0;j<5;j++)
printf("%d ",a[i][j]);
printf(" ");
for(j=0;j<5;j++)
printf("%d ",b[i][j]);
printf(" ");
for(j=0;j<5;j++)
printf("%d ",c[i][j]);
printf("/n");
}
}
void f5()//求层级数
{
printf("输出每一层的层级数/n");
int t=1;
for(int n=0;n<5;n++)
for(int i=0;i<5;i++)
{
int flag=1;
int m=0;
for(int j=0;j<5;j++)
{
m +=a[i][j];
if(a[i][j]!=c[i][j])
{
flag=0;
break;
}
}
if(m==0)//主要是为了防止当删除1和5之后第一行和第五行的元素都是零,此时a[i]也与c[i]相等
flag=0;
if(flag==1)
{
for(int m=0;m<5;m++)
if(a[i][m]!=0)
printf(" %d ",a[i][m]);
printf(" 的层级数为 %d /n",t);
t++;
f6(i);//传的实参是二维数组的行数,就是要删除可达集合和交集中所有与这一行中不为零且相等的元素
}
}
}
void f6(int m)//删除其中相等的元素或集合,a[][]表示可达集合 c[][]表示可达集合与先行集合的交集
{
int t[5]={0};//用t[]来存放删除第m行中所有不为零的元素。然后将可达集合中所有与t[]相等的元素清零
int n=0;
for(int j=0;j<5;j++)
{
if(c[m][j]!=0)
t[n++]=c[m][j];
}
for(int i=0;i<5;i++)//删除可达集合的元素
{
n=0;
for(int j=0;j<5;j++)
{
if(a[i][j]==t[n])
{
a[i][j]=0;
n++;
}
}
}
for(i=0;i<5;i++)//删除可达集合的元素
{
n=0;
for(int j=0;j<5;j++)
{
if(c[i][j]==t[n])
{
c[i][j]=0;
n++;
}
}
}
/*//输出整个过程
printf("输出 可达集合 可达集合与先行集合的交集/n");
for(i=0;i<5;i++)
{
printf("第%d 行: ",i+1);
for(int j=0;j<5;j++)
printf("%d ",a[i][j]);
printf(" ");
for(j=0;j<5;j++)
printf("%d ",c[i][j]);
printf("/n");
}
*/
}
输出结果:
如果想知道这个过程:就把注释的程序重新编译一遍,就知道整个过程了。