C++2种方式方法实现题目:最大拓扑网络。

发布时间:2024年01月11日

题目:
最大拓扑网络。给定n个节点(0~n-1),每个节点都有其对应的层级(1<=level<=1000)。节点之间有链路连接,比如{0,2}表示节点0和节点2之间可以连接,这个连接是双向的。每个节点可以有多条链路,但只能属于一个层级。最大拓扑网络表示在同一层级下,能用链路直接连接起来的最大节点数量。(比如共有3个节点,节点0,1,2都属于层级1,且给定链路{0,1},{1,2},则它们组成了大小为3的拓扑网络。如果节点0,2属于层级1,节点1属于层级2,则最大拓扑网络大小为1)。

输入:n(代表n个节点)
n个数字(代表每个节点所属的层级)
m(代表共有m条链路)
m行,每行为两个数字(代表每条链路连接的两个节点)

输出:最大拓扑网络的大小

解决思路:
方式1:

首先构建一个图来表示节点之间的连接关系,然后使用深度优先搜索(DFS)或者并查集(Union-Find)来找到每个层级内的最大拓扑网络大小。
以下是使用并查集方法的C++代码实现:

#include <iostream>
#include <vector>
#include <unordered_map>
#include <climits>

using namespace std;

const int MAXN = 10010;
int parent[MAXN];
int rank[MAXN];
int level[MAXN];

// 初始化并查集
void initUnion(int n) {
    for (int i = 0; i < n; ++i) {
        parent[i] = i;
        rank[i] = 1;
        level[i] = INT_MAX;
    }
}

// 查找根节点
int find(int x) {
    if (parent[x] != x) {
        parent[x] = find(parent[x]);
    }
    return parent[x];
}

// 合并两个节点
void unionSet(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y) return;
    if (rank[x] < rank[y]) {
        parent[x] = y;
    } else if (rank[x] > rank[y]) {
        parent[y] = x;
    } else {
        parent[y] = x;
        rank[x]++;
    }
}

// 更新层级信息
void updateLevel(int x, int l) {
    if (level[x] == INT_MAX) {
        level[x] = l;
    }
    for (int i = 0; i < rank[x]; ++i) {
        updateLevel(parent[x], l);
    }
}

int main() {
    int n, m;
    cin >> n >> m;

    // 读入节点层级信息
    for (int i = 0; i < n; ++i) {
        cin >> level[i];
    }

    // 初始化并查集
    initUnion(n);

    // 读入链路信息
    for (int i = 0; i < m; ++i) {
        int x, y;
        cin >> x >> y;
        unionSet(x, y);
    }

    // 找到每个层级的根节点,并更新层级信息
    vector<int> roots(n + 1, 0);
    for (int i = 0; i < n; ++i) {
        roots[level[find(i)]]++;
    }

    // 计算最大拓扑网络大小
    int maxSize = 0;
    for (int i = 1; i <= n; ++i) {
        maxSize = max(maxSize, roots[i] * (i - 1));
    }

    cout << maxSize << endl;

    return 0;
}

这段代码首先读入节点数量n和链路数量m,然后读入每个节点的层级信息。接着初始化并查集,读入链路信息并执行合并操作。之后,找到每个层级的根节点,并更新层级信息。最后,计算最大拓扑网络大小并输出结果。
注意:
level[i]表示节点i的层级。
parent[i]表示节点i的父节点。
rank[i]表示节点i的秩(即深度)。
roots[i]表示层级为i的节点数量。
时间复杂度为O(n * m),其中n是节点数量,m是链路数量。

方式2:
首先,我们使用邻接表表示图结构,并根据输入的链路信息构建图。

然后,我们遍历每个节点,并以每个节点为起点进行广度优先搜索。在搜索过程中,我们使用一个队列来辅助遍历与当前节点相连的节点。如果与当前节点相连的节点未被访问且属于同一层级,则将其标记为已访问,并将其加入队列,并将当前拓扑网络的大小加1。最后,我们更新最大拓扑网络的大小。

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

using namespace std;

int main() {
    int n; // 节点数量
    cin >> n;

    vector<int> level(n); // 每个节点对应的层级
    for (int i = 0; i < n; i++) {
        cin >> level[i];
    }

    int m; // 链路数量
    cin >> m;

    vector<vector<int>> graph(n); // 邻接表表示的图
    for (int i = 0; i < m; i++) {
        int u, v; // 链路连接的两个节点
        cin >> u >> v;
        graph[u].push_back(v);
        graph[v].push_back(u);
    }

    int maxNetworkSize = 0; // 最大拓扑网络的大小

    for (int i = 0; i < n; i++) {
        vector<bool> visited(n, false); // 记录节点是否被访问过
        visited[i] = true;

        queue<int> q;
        q.push(i);

        int networkSize = 1; // 当前拓扑网络的大小

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

            for (int neighbor : graph[node]) {
                if (!visited[neighbor] && level[neighbor] == level[i]) {
                    visited[neighbor] = true;
                    q.push(neighbor);
                    networkSize++;
                }
            }
        }

        maxNetworkSize = max(maxNetworkSize, networkSize);
    }

    cout << maxNetworkSize << endl;

    return 0;
}
文章来源:https://blog.csdn.net/qq_35320456/article/details/135536944
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。