题目:
最大拓扑网络。给定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;
}