gpt4 book ai didi

c# - 如何计算最小二分顶点覆盖?

转载 作者:行者123 更新时间:2023-11-30 14:44:24 24 4
gpt4 key购买 nike

如何在 C# 中计算最小的 bipartite 顶点覆盖?有这样做的代码片段吗?

编辑:虽然对于一般图,问题是 NP-complete,但对于二分图,它在多项式时间内是可解的。我知道它在某种程度上与二分图中的最大匹配有关(根据 Konig 定理),但我无法正确理解该定理,无法将最大二分匹配的结果转换为顶点覆盖。

最佳答案

我能弄明白:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

class VertexCover
{
static void Main(string[] args)
{
var v = new VertexCover();
v.ParseInput();
v.FindVertexCover();
v.PrintResults();
}

private void PrintResults()
{
Console.WriteLine(String.Join(" ", VertexCoverResult.Select(x => x.ToString()).ToArray()));
}

private void FindVertexCover()
{
FindBipartiteMatching();

var TreeSet = new HashSet<int>();
foreach (var v in LeftVertices)
if (Matching[v] < 0)
DepthFirstSearch(TreeSet, v, false);

VertexCoverResult = new HashSet<int>(LeftVertices.Except(TreeSet).Union(RightVertices.Intersect(TreeSet)));
}

private void DepthFirstSearch(HashSet<int> TreeSet, int v, bool left)
{
if (TreeSet.Contains(v))
return;
TreeSet.Add(v);
if (left) {
foreach (var u in Edges[v])
if (u != Matching[v])
DepthFirstSearch(TreeSet, u, true);
} else if (Matching[v] >= 0)
DepthFirstSearch(TreeSet, Matching[v], false);

}

private void FindBipartiteMatching()
{
Bicolorate();
Matching = Enumerable.Repeat(-1, VertexCount).ToArray();
var cnt = 0;
foreach (var i in LeftVertices) {
var seen = new bool[VertexCount];
if (BipartiteMatchingInternal(seen, i)) cnt++;
}
}

private bool BipartiteMatchingInternal(bool[] seen, int u)
{
foreach (var v in Edges[u]) {
if (seen[v]) continue;
seen[v] = true;
if (Matching[v] < 0 || BipartiteMatchingInternal(seen, Matching[v])) {
Matching[u] = v;
Matching[v] = u;
return true;
}
}
return false;
}

private void Bicolorate()
{
LeftVertices = new HashSet<int>();
RightVertices = new HashSet<int>();

var colors = new int[VertexCount];
for (int i = 0; i < VertexCount; ++i)
if (colors[i] == 0 && !BicolorateInternal(colors, i, 1))
throw new InvalidOperationException("Graph is NOT bipartite.");
}

private bool BicolorateInternal(int[] colors, int i, int color)
{
if (colors[i] == 0) {
if (color == 1) LeftVertices.Add(i);
else RightVertices.Add(i);
colors[i] = color;
} else if (colors[i] != color)
return false;
else
return true;
foreach (var j in Edges[i])
if (!BicolorateInternal(colors, j, 3 - color))
return false;
return true;
}

private int VertexCount;
private HashSet<int>[] Edges;
private HashSet<int> LeftVertices;
private HashSet<int> RightVertices;
private HashSet<int> VertexCoverResult;
private int[] Matching;

private void ReadIntegerPair(out int x, out int y)
{
var input = Console.ReadLine();
var splitted = input.Split(new char[] { ' ' }, 2);
x = int.Parse(splitted[0]);
y = int.Parse(splitted[1]);
}

private void ParseInput()
{
int EdgeCount;
ReadIntegerPair(out VertexCount, out EdgeCount);
Edges = new HashSet<int>[VertexCount];
for (int i = 0; i < Edges.Length; ++i)
Edges[i] = new HashSet<int>();

for (int i = 0; i < EdgeCount; i++) {
int x, y;
ReadIntegerPair(out x, out y);
Edges[x].Add(y);
Edges[y].Add(x);
}
}
}

如您所见,这段代码在多项式时间内解决了这个问题。

关于c# - 如何计算最小二分顶点覆盖?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/521525/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com