检查哪个玩家访问的节点数量更多

data structurec++programming

为了确定哪个玩家访问了图表中更多的节点,我们将使用图表遍历算法,例如深度优先搜索 (DFS) 或广度优先搜索 (BFS)。从给定的节点开始,我们浏览图表,跟踪每个玩家经过的节点数。通过比较遍历结束时的计数,我们可以确定哪个玩家经过了更多的节点。DFS 通过尽可能深入地搜索图表,然后回溯,而 BFS 则逐层搜索图表。拥有下一个已访问枢纽的玩家在图表中的覆盖范围更广。

使用的方法

  • BFS

  • 修改后的 BSF

BFS

BFS 通过逐级访问顶点来调查图表。从给定的顶点开始,它会在某个点访问其所有邻居,然后转到它们的邻居。在这种情况下,我们为每个顶点初始化 BFS 计算,并且对于每个顶点,我们访问其邻居以检查任意两个邻居之间是否存在边。如果存在这样的边,我们会查看给定的条件是否得到满足。如果条件满足,则我们找到了一个长度为 3 的循环。如果在调查所有顶点后仍未找到这样的循环,则我们得出结论,图表中没有满足给定条件的长度为 3 的循环。

算法

  • 初始化一条线并清除集合。

  • 对于图中的每个顶点 v:

  • 将 V 排入队列。

  • 将 v 添加到访问集。

  • 当该线不可清除时,执行以下操作:

  • 从队列中出列顶点 U。

  • 对于 u 的每个邻居 w:

  • 如果 w 不在已去集:

  • 将 w 添加到已去集。

  • 将 W 排入队列。

  • 检查 u 和 w 之间是否有边。

  • 如果存在边并且满足给定条件,则返回 true。

  • 如果未找到满足条件的长度为 3 的循环,则返回 false。

  • BFS 计算通过逐级转到顶点来调查图表,使我们能够检查长度为 3 的循环并确认给定条件。

示例

#include <iostream>
#include <vector>
#include <queue>
#include <unordered_set>

using namespace std;

bool hasCycleOfLengthThree(vector<vector<int>>& graph, vector<bool>& visited, int start) {
    queue<int> q;
    unordered_set<int> visitedSet;

    q.push(start);
    visited[start] = true;

    while (!q.empty()) {
        int u = q.front();
        q.pop();

        for (int w : graph[u]) {
            if (!visited[w]) {
                visited[w] = true;
                q.push(w);

                // 检查 u 和 w 之间是否存在边
                for (int x : graph[w]) {
                    if (x != u && visited[x]) {
                        // 满足长度为 3 的循环条件
                        return true;
                    }
                }
            }
        }
    }

    return false;
}

bool hasCycleOfLengthThree(vector<vector<int>>& graph) {
    int n = graph.size();
    vector<bool> visited(n, false);

    for (int i = 0; i < n; i++) {
        if (!visited[i] && hasCycleOfLengthThree(graph, visited, i)) {
            return true;
        }
    }

    return false;
}

int main() {
    int n = 12; // 顶点数
    int m = 34; // 边数
    
    vector<vector<int>> graph(n);
    
    // 用于测试的硬编码边
    vector<pair<int, int>> edge = {
        {0, 1}, {0, 2}, {0, 3}, {1, 4}, {1, 5}, {2, 6}, {3, 7}, {3, 8}, {4, 9},
        {5, 9}, {6, 10}, {7, 11}, {8, 11}, {9, 11}, {10, 11}
    };
    
    for (const auto& edge : edge) {
        int u = edge.first;
        int v = edge.second;
        
        graph[u].push_back(v);
        graph[v].push_back(u);
    }
    
    int start = 0; // 起始数字
    int end = 11; // 结束数字

    if (start >= 0 && start < n && end >= 0 && end < n) {
        if (hasCycleOfLengthThree(graph)) {
            cout << "该图包含满足给定条件的长度为 3 的循环。\n";
        } else {
            cout << "该图不包含满足给定条件的长度为 3 的循环。\n";
        }
    } else {
        cout << "起始或结束数字无效。\n";
    }
    
    return 0;
}

输出

该图包含满足给定条件的长度为 3 的循环。

修改后的 BSF

BFS 首先选择一个起始中心,然后探索其所有邻居几次,然后再转到它们的邻居。在这种平衡方法中,我们将每个中心作为起始中心,并从该中心执行 BFS。在 BFS 遍历过程中,我们跟踪距离起始中心 2 的中心。如果这些中心点中的任何一个都有一条返回起始中心的边,那么就存在一个长度为 3 的循环,满足给定的条件。如果在尝试了所有可能的起始中心后仍未找到这样的循环,则图表中没有长度为 3 的循环满足条件。

算法

  • 选择一个起始顶点并将其标记为已访问。

  • 用起始顶点初始化一条线。

  • 当该线未清除时,请执行以下步骤:

    • 从队列前面出队一个顶点。

    • 访问出队顶点的所有未访问邻居。

  • 检查当前顶点及其条件是否满足邻居。

  • 如果条件满足,并且任何邻居将起始顶点作为邻居,则存在长度为 3 的循环。

  • c. 检查已到达的邻居并将其入队。

  • 如果在调查所有顶点后未找到满足条件的长度为 3 的循环,则图表中不存在这样的循环。

示例

#include <iostream>
#include <queue>
#include <vector>

using namespace std;

bool hasCycle(vector<vector<int>>& graph, int start) {
    int n = graph.size();
    vector<int> distance(n, -1); // 每个节点距起点的距离
    queue<int> q;

    distance[start] = 0;
    q.push(start);

    while (!q.empty()) {
        int current = q.front();
        q.pop();

        for (int neighbor : graph[current]) {
            if (distance[neighbor] == -1) {
                distance[neighbor] = distance[current] + 1;
                q.push(neighbor);
            }
            else if (distance[neighbor] == 2 && neighbor != start) {
                return true; // 找到长度为 3 的循环
            }
        }
    }

    return false; // 未找到长度为 3 的循环
}

bool hasCycleOfLength3(vector<vector<int>>& graph) {
    int n = graph.size();

    for (int i = 0; i < n; i++) {
        if (hasCycle(graph, i)) {
            return true; // 从节点 i 找到长度为 3 的环
        }
    }

    return false; // 未找到长度为 3 的循环
}

int main() {
    int n = 5;
    int m = 6;

    vector<vector<int>> graph(n);

    // Define the edges
    vector<pair<int, int>> edges = {{0, 1}, {1, 2}, {2, 3}, {3, 4}, {4, 0}, {1, 4}};

    // 将边添加到图
    for (auto edge : edge) {
        int u = edge.first;
        int v = edge.second;
        graph[u].push_back(v);
        graph[v].push_back(u);
    }
    
    if (hasCycleOfLength3(gr​​aph)) {
        cout << "存在满足给定条件的长度为 3 的循环。" << endl;
    }
    else {
        cout << "不存在满足给定条件的长度为 3 的循环。" << endl;
    }
    
    return 0;
}

输出

存在满足给定条件的长度为 3 的循环。

结论

本文探讨了决定哪个玩家访问图表中更多枢纽的问题。它介绍了两种方法:广度优先 (BFS) 和调整后的 BFS 算法。BFS 算法逐级调查图表,而调整后的 BFS 算法则专注于识别满足给定条件的长度为 3 的循环。本文对这两种算法进行了逐点说明,并比较了 C 的使用情况。这些算法支持比较不同玩家访问中心的次数,并有助于确定哪个玩家在图表中的覆盖范围更广。


相关文章