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