参考程序(回溯+剪枝)
#include <iostream>
#include <vector>
using namespace std;
int N, M;
vector<vector<int>> graph; // 邻接表
vector<bool> visited;
int maxCount = 0;
void backtrack(int node, int count) {
if (node == N) { // 遍历到所有节点
maxCount = max(maxCount, count);
return;
}
// 检查是否可以选择当前节点
bool canPick = true;
for (int i = 0; i < node; i++) {
if (visited[i] && graph[node][i]) { // 冲突
canPick = false;
break;
}
}
// 选择当前节点
if (canPick) {
visited[node] = true;
backtrack(node + 1, count + 1);
visited[node] = false;
}
// 不选择当前节点
backtrack(node + 1, count);
}
int main() {
cin >> N >> M;
graph.resize(N, vector<int>(N, 0));
visited.resize(N, false);
// 输入相冲信息,构建邻接表
for (int i = 0; i < M; i++) {
int u, v;
cin >> u >> v;
u--; v--;
graph[u][v] = graph[v][u] = 1; // 无向边
}
backtrack(0, 0); // 从第0个节点开始回溯
cout << maxCount << endl;
return 0;
}
参考程序(贪心算)
#include <iostream>
#include <vector>
#include <set>
using namespace std;
int main() {
int N, M;
cin >> N >> M;
vector<set<int>> graph(N); // 邻接表表示图
for (int i = 0; i < M; i++) {
int u, v;
cin >> u >> v;
u--; v--;
graph[u].insert(v);
graph[v].insert(u);
}
vector<bool> visited(N, false);
int maxCount = 0;
while (true) {
// 找到度数最小的节点
int minDegree = N + 1, selected = -1;
for (int i = 0; i < N; i++) {
if (!visited[i] && graph[i].size() < minDegree) {
minDegree = graph[i].size();
selected = i;
}
}
if (selected == -1) break; // 没有可以选择的节点了
// 选择该节点加入独立集
maxCount++;
visited[selected] = true;
// 移除与该节点相邻的节点
for (int neighbor : graph[selected]) {
visited[neighbor] = true;
}
}
cout << maxCount << endl;
return 0;
}