最近写代码遇到一个问题。如图一个3*3*3的Cube
当两个立方体之间共享一个面,称为面邻居(R-6);当两个立方体仅共享一条边,称为边邻居(R-18);仅共享一个点,称为点邻居(R-26)。在细化骨架的算法中,判断一个体素是否为简单体素的时候要判断,删除体素前后欧拉示性数、连通分量数是否发生改变。这个连通分量数,把立方体当成图中的点,两个立方体之间点相邻代表他们之间有边,可以转换成图深搜、广搜去判断没有中心体素前后的连通分量数。在体网格模型里,从点邻接关系独立抽出中心体素的R-26有点麻烦,所以改变角度,从八分圆的邻接关系去判断。八分圆就是中心体素八个顶点为中心的2*2*2的Cube,当两个八分圆之间有重叠部分代表两个八分圆相邻。
因此问题还是回到图的连通判断。判断图的连通性可以深搜、广搜、并查集。
下面这道题目的场景非常相似。
班上有 N 名学生。其中有些人是朋友,有些则不是。他们的友谊具有是传递性。如果已知 A 是 B 的朋友,B 是 C 的朋友,那么我们可以认为 A 也是 C 的朋友。所谓的朋友圈,是指所有朋友的集合。
给定一个 N * N 的矩阵 M,表示班级中学生之间的朋友关系。如果M[i][j] = 1,表示已知第 i 个和 j 个学生互为朋友关系,否则为不知道。你必须输出所有学生中的已知的朋友圈总数。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/friend-circles
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
第一版可以AC的代码。结果:52ms,14.1mb。
//Union_Find
class solver {
public:
solver(int n) {
count = n;
root.resize(n);
for (int i = 0; i < n; i++)
root[i] = i;
}
//connect x and y
void connect(int x, int y) {
int xroot = find(x);
int yroot = find(y);
if (xroot == yroot) {
return;
}
root[yroot] = xroot;
count--;
}
//judge two point is neighbor
bool isConnected(int x, int y) {
int xroot = find(x);
int yroot = find(y);
return xroot == yroot;
}
//return count
int count_num() {
return count;
}
private:
int count;
vector<int> root;
//get root of x
int find(int x) {
while (root[x] != x)
x = root[x];
return x;
}
};
//LeetCode内置的判题系统太复杂,上面写了一个求解器来包含并查集的函数,简单易懂
class Solution {
public:
int findCircleNum(vector<