Минимальное вершинное покрытие, максимальное независимое множество
Перейти к навигации
Перейти к поиску
Минимальное вершинное покрытие (minimum vertex cover, MVC) — минимальный по размеру набор вершин, содержащий хотя бы один конец каждого ребра.
В двудольном графе размер минимального вершинного покрытия совпадает с размером максимального паросочетания.
Максимальное независимое множество (maximum independent set, MIS) — максимальный по размеру набор вершин, никакие две из которых не соединены ребром.
В любом графе максимальное независимое множество — дополнение минимального вершинного покрытия (содержит все вершины, не входящие в минимальное вершинное покрытие).
Построение
|
|
|
|
struct Data { int an = 0, bn = 0; vector<pair<int, int>> edges; }; Data readData() { Data d; int edgeCount; cin >> d.an >> d.bn >> edgeCount; d.edges.resize(edgeCount); for (auto &[a, b] : d.edges) cin >> a >> b; return d; } Graph computeMaxMatching(Data &d) { Graph g(1 + d.an + d.bn + 1); for (int a = 0; a < d.an; a++) g.addEdge(0, 1 + a, 1); for (auto &[a, b] : d.edges) g.addEdge(1 + a, 1 + d.an + b, 1); for (int b = 0; b < d.bn; b++) g.addEdge(1 + d.an + b, 1 + d.an + d.bn, 1); g.maxFlow(0, 1 + d.an + d.bn); return g; } vector<vector<int>> buildMVCGraph(Data &d, Graph &g) { vector<vector<int>> mg(d.an + d.bn); for (auto &[a, b, _, flow] : g.edges) { if (0 != a && b != 1 + d.an + d.bn) { if (flow) mg[b - 1].push_back(a - 1); else mg[a - 1].push_back(b - 1); } } return mg; } void dfs(vector<vector<int>> &g, int v, vector<int> &visited) { visited[v] = 1; for (int to : g[v]) if (!visited[to]) dfs(g, to, visited); } pair<vector<int>, vector<int>> computeMVC(Data &d, vector<vector<int>> &g) { set<int> startVertices; for (int i = 0; i < d.an; i++) startVertices.insert(i); for (auto &row : g) for (int to : row) startVertices.erase(to); vector<int> visited(d.an + d.bn); for (int v : startVertices) dfs(g, v, visited); vector<int> a; for (int i = 0; i < d.an; i++) if (!visited[i]) a.push_back(i); vector<int> b; for (int i = 0; i < d.bn; i++) if (visited[d.an + i]) b.push_back(i); return { a, b }; } void solve() { auto d = readData(); auto g = computeMaxMatching(d); auto mg = buildMVCGraph(d, g); auto [a, b] = computeMVC(d, mg); } |
struct Data { int an = 0, bn = 0; vector<pair<int, int>> edges; }; Data readData() { Data d; int edgeCount; cin >> d.an >> d.bn >> edgeCount; d.edges.resize(edgeCount); for (auto &[a, b] : d.edges) cin >> a >> b; return d; } Graph computeMaxMatching(Data &d) { Graph g(1 + d.an + d.bn + 1); for (int a = 0; a < d.an; a++) g.addEdge(0, 1 + a, 1); for (auto &[a, b] : d.edges) g.addEdge(1 + a, 1 + d.an + b, 1); for (int b = 0; b < d.bn; b++) g.addEdge(1 + d.an + b, 1 + d.an + d.bn, 1); g.maxFlow(0, 1 + d.an + d.bn); return g; } vector<vector<int>> buildMVCGraph(Data &d, Graph &g) { vector<vector<int>> mg(d.an + d.bn); for (auto &[a, b, _, flow] : g.edges) { if (0 != a && b != 1 + d.an + d.bn) { if (flow) mg[b - 1].push_back(a - 1); else mg[a - 1].push_back(b - 1); } } return mg; } void dfs(vector<vector<int>> &g, int v, vector<int> &visited) { visited[v] = 1; for (int to : g[v]) if (!visited[to]) dfs(g, to, visited); } pair<vector<int>, vector<int>> computeMIS(Data &d, vector<vector<int>> &g) { set<int> startVertices; for (int i = 0; i < d.an; i++) startVertices.insert(i); for (auto &row : g) for (int to : row) startVertices.erase(to); vector<int> visited(d.an + d.bn); for (int v : startVertices) dfs(g, v, visited); vector<int> a; for (int i = 0; i < d.an; i++) if (visited[i]) a.push_back(i); vector<int> b; for (int i = 0; i < d.bn; i++) if (!visited[d.an + i]) b.push_back(i); return { a, b }; } void solve() { auto d = readData(); auto g = computeMaxMatching(d); auto mg = buildMVCGraph(d, g); auto [a, b] = computeMIS(d, mg); } |
Ссылки
Теория: