如何在C#中计算最小二分顶点覆盖率?有代码片段可以这样做吗?
编辑:虽然一般图的问题是NP完全的,但对于二部图来说,它可以在多项式时间内解决。我知道这与二部图中的最大匹配有关(根据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(); foreach (var v in LeftVertices) if (Matching[v] < 0) DepthFirstSearch(TreeSet, v, false); VertexCoverResult = new HashSet (LeftVertices.Except(TreeSet).Union(RightVertices.Intersect(TreeSet))); } private void DepthFirstSearch(HashSet 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 (); RightVertices = new HashSet (); 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 [] Edges; private HashSet LeftVertices; private HashSet RightVertices; private HashSet 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 [VertexCount]; for (int i = 0; i < Edges.Length; ++i) Edges[i] = new HashSet (); for (int i = 0; i < EdgeCount; i++) { int x, y; ReadIntegerPair(out x, out y); Edges[x].Add(y); Edges[y].Add(x); } } }
如您所见,此代码解决了多项式时间问题。