试题 算法训练 盾神与离散老师2
资源限制
**时间限制:**1.0s 内存限制:256.0MB
问题描述
有一天,盾神觉得自己离散课快要挂了,于是亲自找到离散老师WH,请教如何才能不挂科。WH老师说,只要你做出下面那题,你就可以不挂了!但是盾神不会做T_T只能请教你了。
有N个人,i和j可能认识,可能不认识。i一定认识i。如果i认识j,j不一定认识i。但是如果i认识j,j认识k,i必定认识k。给出目前掌握的N个人互相的认识关系,求用已知的关系推断出来的N个人互相的人事关系。
输入格式
输入第一行为一个数N。
接下来是一个NN的矩阵,第i行第j个数是1的话表示i认识j,0的话表示i不一定认识j。不会出现除0和1之外的其他数。数与数之间用一个空格隔开。第i行第i列不一定是1。
输出格式
输出一个NN的矩阵,第i行第j列的意思如输入。数与数之间用一个空格隔开。第i行第i列必须是1。
样例输入
3
0 1 0
0 0 1
0 0 0
样例输出
1 1 1
0 1 1
0 0 1
数据规模和约定
N<=500
分析:
传递认识的话,我第一时间想到的是数组,n行n列直接构造n维数组,可是,怎么传递认识呢,想了想,我们可以通过数组下标来操作,比如:a[1][3]=1代表1认识3,后面出现了a[3][2]=1,那么a[1][2]=1,很明显是第一个的行和第二个的列,我们可以构造单独的一个for循环去寻找可传递的数,另外,值得注意的是**,不止传一次,要是a[2][4]=1,那么还要在传递**,所以给个大的while循环重复一下就可以了。
废话不多说。
附上代码:
#include<iostream>
using namespace std;
int a[1000][1000] = {0};
int main()
{
int n, i, j, k;
cin >> n;
for (i = 1; i <=n ; i++)
{
for (j = 1; j <= n; j++)
{
cin >> a[i][j];
}
}
int s = 2;
//主要算法
for (i = 1; i <= n; i++)a[i][i] = 1;
while(s--)//重新在认识一下扩大认识范围
{for (i = 1; i <= n; i++)
{
for (j = 1; j <= n; j++)
{
//主要语句:起到传递认识的作用
for (k = 1; k <= n; k++)
{
if (a[j][k] == 1&&a[i][j] == 1)
a[i][k] = 1;
}
}
} }
for (i = 1; i <= n; i++)//输出
{
for (j = 1; j <= n; j++)
{
cout<< a[i][j]<<" ";
}
cout << endl;
}
return 0;
}
运行结果: