NPC系列文章(1)---最小覆盖问题Set Cover Problem的一种贪心算法

QT = core

CONFIG += c++17 cmdline

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
        main.cpp \
        simplegraph.cpp

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

HEADERS += \
    commondatastructure.h \
    simplegraph.h
#include "simplegraph.h"
using namespace std;

int main(int argc, char *argv[])
{
    /*
    (0)--(1)--(2)
    |   / \   |
    |  /   \  |
    | /     \ |
    (3)-------(4)
    */
    GRAPH_ADJARRAY_VECTOR graph = {
        {0, 1, 0, 1, 0},
           {0, 1, 1, 1},
              {0, 0, 1},
                 {0, 1},
                    {0}
    };
    cout << "G Upper Triangle Matrix" << endl;
    SimpleGraph G(graph);
    G.help();

    cout << "Computing Min Vertex Cover..." << endl;
    VERTEXCOVER coverSet = G.getVertexCover();

    cout << "Print Min Vertex Cover..." << endl;
    SimpleGraph::printVertexSet(coverSet);

    cout << "Finish!!!" << endl;
}
#ifndef COMMONDATASTRUCTURE_H
#define COMMONDATASTRUCTURE_H

#include 
#include 
#include 
#include 
#include 
#include 

#include "assert.h"
using namespace std;

const int MAXVERTEX = 40;

typedef set ADJPOINTSSET;  //相邻顶点集合
typedef pair ADJPOINTSPAIR; //相邻顶点集合与其基数(大小)
typedef map VERTEXMAP;  //顶点与它的相邻顶点集合的映射
typedef VERTEXMAP GRAPH_ADJLIST_MAP; //G的邻接表List表示

typedef vector > GRAPH_ADJARRAY_VECTOR;  //G的邻接矩阵Vector表示
typedef vector OFFSET_VECTOR;

typedef ADJPOINTSSET VERTEXCOVER;

#endif // COMMONDATASTRUCTURE_H
#ifndef SIMPLEGRAPH_H
#define SIMPLEGRAPH_H

#include "commondatastructure.h"

class SimpleGraph
{
public:
    SimpleGraph(const GRAPH_ADJARRAY_VECTOR adjgraph);

    VERTEXCOVER getVertexCover();

    void help(); //print adj array
    void print(); //print adj list

    void inc(int keyVertex, int targetVertex);
    void dec(int keyVertex, int targetVertex);

    static void printVertexSet(VERTEXCOVER s);

    static OFFSET_VECTOR globalOffset;

private:
    GRAPH_ADJLIST_MAP m_dstAdjList;
    GRAPH_ADJARRAY_VECTOR m_srcAdjArray;

    void adjArray2adjList(const GRAPH_ADJARRAY_VECTOR &srcAdjArray, GRAPH_ADJLIST_MAP &dstAdjList);
};

#endif // SIMPLEGRAPH_H
#include "simplegraph.h"

#define PRINTINFO 1

OFFSET_VECTOR SimpleGraph::globalOffset = \
{ \
    0,1,2,3,4,5,6,7,8,9 \
    ,10,11,12,13,14,15,16,17,18,19 \
    ,20,21,22,23,24,25,26,27,28,29 \
    ,30,31,32,33,34,35,36,37,38,39 \
};

SimpleGraph::SimpleGraph(const GRAPH_ADJARRAY_VECTOR adjgraph)
    :m_srcAdjArray(adjgraph)
{
    adjArray2adjList(m_srcAdjArray,m_dstAdjList);
}

void SimpleGraph::adjArray2adjList(const GRAPH_ADJARRAY_VECTOR &srcAdjArray, GRAPH_ADJLIST_MAP &dstAdjList)
{
    int ncount;

    assert( srcAdjArray.size() < MAXVERTEX);

    for (int i = 0; i < srcAdjArray.size(); ++i){
        ADJPOINTSSET s;
        ncount = 0;
        for(int j= 0; j< srcAdjArray[i].size(); ++j)
        {
            if(srcAdjArray[i][j] != 0)
            {
                s.insert(j + globalOffset[i]);
                ncount ++;
            }
        }

        ADJPOINTSPAIR adjPointsPair(ncount,s);
        dstAdjList.insert(make_pair(i,adjPointsPair));
    }

    GRAPH_ADJLIST_MAP::iterator it;
    for(it = m_dstAdjList.begin(); it != m_dstAdjList.end(); it++)
    {
        ADJPOINTSSET s = it->second.second;
        ADJPOINTSSET::iterator adjset_it;
        for(adjset_it = s.begin(); adjset_it != s.end(); adjset_it++) {
            if(*adjset_it > it->first)
            {
                inc(*adjset_it, it->first);
            }
        }
    }

}

VERTEXCOVER SimpleGraph::getVertexCover()
{
    VERTEXCOVER s;
    ADJPOINTSSET tmps;
    ADJPOINTSSET::iterator adjset_it;

#if PRINTINFO
    cout << "====================================================" << endl;
    cout << "v d s" << endl;
    cout << "-----" << endl;

    print();
#endif
    //1.put the highest degree vertex in the cover set
    GRAPH_ADJLIST_MAP::iterator it, it_target;

    while (1) {
#if PRINTINFO
        cout << "step1.put the highest degree vertex in the cover set" << endl;
#endif
        int nMaxDegree = 0;
        it_target = m_dstAdjList.begin();
        for(it = m_dstAdjList.begin(); it != m_dstAdjList.end(); it++)
        {
//            cout << it->first << " " << it->second.first << endl;
            if(nMaxDegree < it->second.first)
            {
                nMaxDegree = it->second.first;
                it_target = it;
            }
        }

#if PRINTINFO
        cout << "it_target is " << it_target->first << " " << it_target->second.first << endl;
#endif
        if(it_target->second.first == 0) break;

        s.insert(it_target->first);

#if PRINTINFO
        cout << "one of highest degree vertex is vertex: " << it_target->first << endl;

        SimpleGraph::printVertexSet(s);

        cout << "step2.update the degree of vertexes in the list.if 0, remove it." << endl;
#endif
        //2.update the degree of vertexes in the list.if 0, remove it.

        tmps= it_target->second.second;
        for(adjset_it = tmps.begin(); adjset_it != tmps.end(); adjset_it++) {
            dec(*adjset_it, it_target->first);
        }

        it_target->second.first = 0;
        it_target->second.second.clear();

#if PRINTINFO
        SimpleGraph::print();
#endif
    }

#if PRINTINFO
    cout << "step3.Exit the loop,get the one of cover set" << endl;
#endif

    return s;
}

void SimpleGraph::help()
{
    if(m_srcAdjArray.size() == 0)
    {
        cout << "Adjacency Array vector is null\n";
        return;
    }

    int i = 0;
    for (auto& line : m_srcAdjArray) {
        for (int j=0; j< i; j++) {
            cout << "  ";
        }
        for (const auto& v : line) {
            cout << v << " ";
        }
        cout << endl;
        i++;
    }
}

void SimpleGraph::printVertexSet(VERTEXCOVER s)
{
#if 1
    ADJPOINTSSET::iterator adjset_it;
    cout << "{";
    for(adjset_it = s.begin(); adjset_it != s.end(); adjset_it++) {
        cout << *adjset_it << " ";
    }
    cout << "}" << endl;
#endif
}

void SimpleGraph::print()
{
#if 1
    GRAPH_ADJLIST_MAP::iterator it;
    for(it = m_dstAdjList.begin(); it != m_dstAdjList.end(); it++)
    {
        //输出Node的key值,度数值 和相邻顶点集合
        cout << it->first << " " << it->second.first << " ";
        SimpleGraph::printVertexSet(it->second.second);
    }
#endif
}

void SimpleGraph::inc(int keyVertex, int targetVertex)
{
    m_dstAdjList.at(keyVertex).first += 1;
    m_dstAdjList.at(keyVertex).second.insert(targetVertex);
}

void SimpleGraph::dec(int keyVertex, int targetVertex)
{
    m_dstAdjList.at(keyVertex).first -= 1;
    m_dstAdjList.at(keyVertex).second.erase(targetVertex);
}

你可能感兴趣的:(贪心算法,算法,NPC,SCP)