当前位置:  开发笔记 > 编程语言 > 正文

如何计算最小二分顶点覆盖率?

如何解决《如何计算最小二分顶点覆盖率?》经验,为你挑选了1个好方法。

如何在C#中计算最小二分顶点覆盖率?有代码片段可以这样做吗?

编辑:虽然一般图的问题是NP完全的,但对于二部图来说,它可以在多项式时间内解决。我知道这与二部图中的最大匹配有关(根据Konig定理),但是我无法正确理解该定理,无法将最大二部匹配的结果转换为顶点覆盖。



1> 小智..:

我可以弄清楚:

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);
        }
    }
}

如您所见,此代码解决了多项式时间问题。

推荐阅读
mylvfamily
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有