Description
给定有向图的邻接矩阵A,其元素定义为:若存在顶点i到顶点j的有向边则A[i,j]=1
,若没有有向边则A[i,j]= 0
。试求A
的可达闭包矩阵A*
,其元素定义为:若存在顶点i
到顶点j
的有向路径则A*[i,j]=1
,若没有有向路径则A*[i,j]= 0
。
Input
第1行顶点个数n
第2行开始的n行有向图的邻接矩阵,元素之间由空格分开
Output
有向图的可达闭包矩阵A*
,元素之间由空格分开
Sample
#0
Input
Copy
4 0 1 0 1 0 0 1 0 0 0 0 0 0 0 0 0
Output
Copy
0 1 1 1 0 0 1 0 0 0 0 0 0 0 0 0
思路:
floyd本来我们用来求最短路的问题的,但是我们可以用来求是否可达。
floyd中的三个循环
k是中转点,i是起点,j是终点。
求最短路:
i 到 j 的边是否小于通过 k 中转的点的边,如 i->k,k>j,会不会距离更短。
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]);
求是否可达则一样:
如果i j本来可达,则dp[i][j]=1
若本来不可达,则 i 是否可以通过中转点到 j,如果 i 到 k有一条边,k 到 j有一条边,则 i 是不是可以到 j
if (dp[i][k] && dp[k][j] || dp[i][j]) ///如果i到k有一条边,k到j有一条边,所以i到j可达
{
dp[i][j] = 1;
}
主要代码实现:
代码
#include <iostream>
using namespace std;
const int maxn = 1e2 + 10;
int n;
int dp[maxn][maxn];///邻接矩阵存边
void irit()///初始化
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
dp[i][j] = 0;
}
}
}
void floyd()
{
for (int k = 0; k < n; k++)///选择中转点
{
for (int i = 0; i < n; i++)///选择起点
{
for (int j = 0; j < n; j++)///选择终点
{
if (dp[i][k] && dp[k][j] || dp[i][j])///如果i到k有一条边,k到j有一条边,所以i到j可达
{
dp[i][j] = 1;
}
}
}
}
}
int main()
{
cin >> n;
irit();
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cin >> dp[i][j];
}
}
floyd();
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cout << dp[i][j] << " ";///输出可达闭包矩阵
}
cout << endl;
}
return 0;
}