问题描述
wzy 给你了一个 n×n 的 01 矩阵 a,你需要求一下满足 ai,j=ai,k=aj,k=1 的三元组 (i,j,k) 的个数。
注:给定的矩阵一定满足 ai,j=aj,i。同时,(1,2,3),(3,2,1)这种视作同一个三元组,且 i≠j,j≠k,i≠k。
输入格式
第一行输入一个数字 nn,表示矩阵大小。(1≤n≤800)
接来下 n 行,每行一个长度为 n 的 01 串。
输出格式
输出满足条件的三元组数量。
样例输入
4
0011
0011
1101
1110
样例输出
2
运行限制
语言 | 最大运行时间 | 最大运行内存 |
---|---|---|
C++ | 1s | 256M |
C | 1s | 256M |
Java | 2s | 256M |
Python3 | 3s | 256M |
解题思路
我们需要找到满足条件的三元组 (i, j, k),使得 a[i][j] = a[i][k] = a[j][k] = 1,并且 i, j, k 互不相同。由于矩阵是对称的,a[i][j] = a[j][i],因此我们可以简化问题。
我们可以将问题转化为:对于每一个 i,找到所有满足 a[i][j] = 1 且 a[i][k] = 1 且 a[j][k] = 1 的 j 和 k。
具体步骤如下:
①遍历每一个 i:从 0 到 n-1。
②找到所有与 i 相连的 j:即 a[i][j] = 1 的 j。
③对于每一个 j,找到所有与 i 和 j 都相连的 k:即 a[i][k] = 1 且 a[j][k] = 1 的 k。
④统计满足条件的三元组:注意避免重复计数。
为了避免重复计数,我们可以只考虑 i < j < k 的情况,这样每个三元组只会被计算一次。
应用方法
我们可以使用三重循环来解决问题:
①外层循环遍历 i。
②中层循环遍历 j,且 j > i。
③内层循环遍历 k,且 k > j。
这样,我们只需要检查 a[i][j], a[i][k], a[j][k] 是否都为 1。
代码答案
编译语言:C++(g++17)
#include <bits/stdc++.h> //包含所有标准库头文件,方便使用各种STL函数和数据结构
using namespace std; //使用标准命名空间,避免写std::
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); //取消同步流,提高输入输出效率
int n;
cin >> n; //读取矩阵的大小n
vector<vector<int>> a(n, vector<int>(n)); //定义nxn的矩阵a
for(int i = 0; i < n; ++ i)
{
string row;
cin >> row; //读取每一行的01字符串
for (int j = 0; j < n; ++j)
{
a[i][j] = row[j] - '0'; //将字符转换为数字存入矩阵a
}
}
long long count = 0; // 计数器,用于统计满足条件的三元组数量
for(int i = 0;i < n;++ i)
{//枚举第一个节点i
for(int j = i + 1;j < n;++ j)
{//枚举第二个节点j,确保j>i以避免重复
if (a[i][j] == 1)
{//如果节点i和j相连
for (int k = j + 1; k < n; ++k)
{//枚举第三个节点k,确保k>j以避免重复
if(a[i][k] == 1 && a[j][k] == 1)
{//如果节点i和k相连,且节点j和k相连
count++; //满足条件,计数器加1
}
}
}
}
}
cout << count << '\n'; //输出满足条件的三元组数量
return 0;
}
代码的复杂度分析
1.时间复杂度:
①外层循环遍历 i,复杂度为 O(n)。
②中层循环遍历 j,复杂度为 O(n)。
③内层循环遍历 k,复杂度为 O(n)。
④总时间复杂度为 O(n^3)。
⑤对于 n = 800,800^3 = 512,000,000,在现代计算机上可以接受。
2.空间复杂度:
①矩阵 a 的大小为 n x n,空间复杂度为 O(n^2)。
②其他变量(如 count)的空间复杂度为 O(1)。
③总空间复杂度为 O(n^2)。
注意事项
1.矩阵的对称性:
题目中说明矩阵是对称的,即 a[i][j] = a[j][i],因此无需额外处理对称性。
2.避免重复计数:
通过限制 i < j < k,可以确保每个三元组只被计算一次。
3.数据类型:
使用 long long 存储计数器 count,因为三元组数量可能非常大。
(最大为 C(n, 3) = n*(n-1)*(n-2)/6,对于 n = 800,约为 85,000,000)
4.输入优化:
使用 ios::sync_with_stdio(0), cin.tie(0), cout.tie(0) 取消同步流,提高输入输出效率。
总结
1.代码功能:
该代码用于统计满足条件的三元组 (i, j, k) 的数量,其中 a[i][j] = a[i][k] = a[j][k] = 1。
2.实现方法:
通过三重循环枚举所有可能的 i, j, k,并检查是否满足条件。
3.优化:
通过限制 i < j < k 避免重复计数,同时利用矩阵的对称性简化问题。
4.适用场景:
适用于 n 较小(如 n ≤ 800)的情况。对于更大的 n,需要进一步优化算法。
5.改进方向:
如果 n 更大,可以考虑使用位运算或其他优化方法减少时间复杂度。