C++如何求有向图中闭合子集的数量给出C++代码
时间: 2024-10-02 13:00:16 浏览: 38
基于C++版本sfntly实现的字体子集化工具
在C++中计算有向图中闭合子集的数量通常涉及到拓扑排序和哈希集合的数据结构。一个闭合子集是指包含起点并且从该节点开始可以遍历回到起点的路径。这个问题可以转化为寻找环的数量,因为每个环对应一个闭合子集。
这里是一个简化版的算法示例,使用了邻接列表表示图,并利用哈希集合记录已经访问过的顶点,避免重复计数环:
```cpp
#include <unordered_set>
#include <vector>
int countClosedSubsets(const std::vector<std::vector<int>>& graph, int n) {
std::vector<bool> visited(n, false);
std::unordered_set<int> inCycle; // 记录在环内的顶点
for (int i = 0; i < n; ++i) {
if (!visited[i]) { // 如果顶点未访问
int cycleCount = dfs(graph, i, visited, &inCycle);
for (int j : inCycle) {
// 对于每个在环内的顶点,每增加一个环都会贡献一个额外的闭合子集
cycleCount++;
}
closedSubsets += cycleCount;
}
}
return closedSubsets;
}
// 深度优先搜索辅助函数
int dfs(const std::vector<std::vector<int>>& graph, int node, std::vector<bool>& visited, std::unordered_set<int>* inCycle) {
visited[node] = true;
inCycle->insert(node);
for (int neighbor : graph[node]) {
if (!visited[neighbor]) {
int subCycleCount = dfs(graph, neighbor, visited, inCycle);
if (*inCycle.find(neighbor) != *inCycle.end()) {
// 遇到环的另一个部分,将当前环的顶点添加到总环数中
subCycleCount--;
}
closedSubsets += subCycleCount;
} else if (*inCycle.find(neighbor) == *inCycle.end()) {
// 已经访问过的邻居不在当前环内,直接跳过
continue;
} else {
// 跨越环的情况,需要减去这个环,因为我们已经处理过它
closedSubsets -= 1;
}
}
// 出环操作
inCycle.erase(node);
visited[node] = false;
return closedSubsets;
}
```
注意,这个代码假设输入的图没有自环,如果有自环则需要稍作修改。此外,`closedSubsets` 初始化为0,在整个过程中累加得到结果。
阅读全文