• NPC系列文章(2)---最小覆盖问题Set Cover Problem的一种贪心算法求全部覆盖集


    1. QT = core
    2. CONFIG += c++11 cmdline
    3. # You can make your code fail to compile if it uses deprecated APIs.
    4. # In order to do so, uncomment the following line.
    5. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
    6. SOURCES += \
    7. cprecisetimer.cpp \
    8. main.cpp \
    9. simplegraph.cpp
    10. # Default rules for deployment.
    11. qnx: target.path = /tmp/$${TARGET}/bin
    12. else: unix:!android: target.path = /opt/$${TARGET}/bin
    13. !isEmpty(target.path): INSTALLS += target
    14. HEADERS += \
    15. commondatastructure.h \
    16. cprecisetimer.h \
    17. simplegraph.h
    1. #ifndef COMMONDATASTRUCTURE_H
    2. #define COMMONDATASTRUCTURE_H
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include "assert.h"
    10. //using namespace std;
    11. const int MAXVERTEX = 40;
    12. typedef std::set<int> ADJPOINTSSET; //相邻顶点集合
    13. typedef std::pair<int, ADJPOINTSSET> ADJPOINTSPAIR; //相邻顶点集合与其基数(大小)
    14. typedef std::map<int, ADJPOINTSPAIR> VERTEXMAP; //顶点与它的相邻顶点集合的映射
    15. typedef VERTEXMAP GRAPH_ADJLIST_MAP; //G的邻接表List表示
    16. typedef std::vectorbool> > GRAPH_ADJARRAY_VECTOR; //G的邻接矩阵Vector表示
    17. typedef std::vector<int> OFFSET_VECTOR;
    18. typedef ADJPOINTSSET VERTEXCOVER;
    19. #endif // COMMONDATASTRUCTURE_H
    1. #ifndef CPRECISETIMER_H
    2. #define CPRECISETIMER_H
    3. #include
    4. class CPreciseTimer
    5. {
    6. public:
    7. CPreciseTimer();
    8. bool SupportsHighResCounter();
    9. void StartTimer();
    10. void StopTimer();
    11. __int64 GetTime();
    12. private:
    13. //Auxiliary Function
    14. void UpdateElapsed();
    15. //Member variables
    16. bool m_bRunning;
    17. __int64 m_i64Start;
    18. __int64 m_i64Elapsed;
    19. //Some auxiliary variables
    20. __int64 m_i64Counts;
    21. LARGE_INTEGER m_liCount;
    22. //Static Variables
    23. static bool sm_bInit;
    24. static bool sm_bPerformanceCounter;
    25. static __int64 sm_i64Freq;
    26. };
    27. inline bool CPreciseTimer::SupportsHighResCounter()
    28. {
    29. return sm_bPerformanceCounter;
    30. }
    31. //Auxiliary Function
    32. inline void CPreciseTimer::UpdateElapsed()
    33. {
    34. if(true == sm_bPerformanceCounter)
    35. {
    36. QueryPerformanceCounter(&m_liCount);
    37. m_i64Counts = ((__int64)m_liCount.HighPart << 32) + (__int64)m_liCount.LowPart;
    38. //Transform in microseconds
    39. (m_i64Counts *= 1000000) /= sm_i64Freq;
    40. }
    41. else
    42. //Transform milliseconds to microseconds
    43. m_i64Counts = (__int64)GetTickCount() * 1000;
    44. if(m_i64Counts > m_i64Start)
    45. m_i64Elapsed = m_i64Counts - m_i64Start;
    46. else
    47. //Eliminate possible number overflow (0x7fffffffffffffff is the maximal __int64 positive number)
    48. m_i64Elapsed = (0x7fffffffffffffff - m_i64Start) + m_i64Counts;
    49. }
    50. #endif // CPRECISETIMER_H
    1. #include "cprecisetimer.h"
    2. bool CPreciseTimer::sm_bInit = false;
    3. bool CPreciseTimer::sm_bPerformanceCounter;
    4. __int64 CPreciseTimer::sm_i64Freq;
    5. //CONSTRUCTOR
    6. CPreciseTimer::CPreciseTimer() : m_i64Start(0), m_i64Elapsed(0), m_bRunning(false)
    7. {
    8. //Only if not already initialized
    9. if(false == sm_bInit)
    10. {
    11. //Initializing some static variables dependent on the system just once
    12. LARGE_INTEGER liFreq;
    13. if(TRUE == QueryPerformanceFrequency(&liFreq))
    14. {
    15. //Only if the system is supporting High Performance
    16. sm_i64Freq = ((__int64)liFreq.HighPart << 32) + (__int64)liFreq.LowPart;
    17. sm_bPerformanceCounter = true;
    18. }
    19. else
    20. sm_bPerformanceCounter = false;
    21. sm_bInit = true;
    22. }
    23. }
    24. void CPreciseTimer::StartTimer()
    25. {
    26. if(true == sm_bPerformanceCounter)
    27. {
    28. QueryPerformanceCounter(&m_liCount);
    29. m_i64Start = ((__int64)m_liCount.HighPart << 32) + (__int64)m_liCount.LowPart;
    30. //Transform in microseconds
    31. (m_i64Start *= 1000000) /= sm_i64Freq;
    32. }
    33. else
    34. //Transform milliseconds to microseconds
    35. m_i64Start = (__int64)GetTickCount() * 1000;
    36. m_bRunning = true;
    37. }
    38. void CPreciseTimer::StopTimer()
    39. {
    40. UpdateElapsed();
    41. m_bRunning = false;
    42. }
    43. __int64 CPreciseTimer::GetTime()
    44. {
    45. if(true == m_bRunning)
    46. UpdateElapsed();
    47. return m_i64Elapsed;
    48. }
    1. #ifndef SIMPLEGRAPH_H
    2. #define SIMPLEGRAPH_H
    3. #include "commondatastructure.h"
    4. class SimpleGraph
    5. {
    6. public:
    7. SimpleGraph(const GRAPH_ADJARRAY_VECTOR adjgraph);
    8. VERTEXCOVER getVertexCover();
    9. void help(); //print adj array
    10. void print(); //print adj list
    11. void inc(int keyVertex, int targetVertex);
    12. void dec(int keyVertex, int targetVertex);
    13. bool checkIsCover(std::vector<int> &vertexSet);
    14. static void printVertexSet(VERTEXCOVER s);
    15. static std::vectorint> > getCombineNK(int n, int k);
    16. static void showCombinationvector( std::vectorint> > va );
    17. static OFFSET_VECTOR globalOffset;
    18. private:
    19. GRAPH_ADJLIST_MAP m_dstAdjList;
    20. GRAPH_ADJARRAY_VECTOR m_srcAdjArray;
    21. void adjArray2adjList(const GRAPH_ADJARRAY_VECTOR &srcAdjArray, GRAPH_ADJLIST_MAP &dstAdjList);
    22. };
    23. #endif // SIMPLEGRAPH_H
    1. #include "simplegraph.h"
    2. #define PRINTINFO 1
    3. //const int N = 10;
    4. //const int K = 5;
    5. OFFSET_VECTOR SimpleGraph::globalOffset = \
    6. { \
    7. 0,1,2,3,4,5,6,7,8,9 \
    8. ,10,11,12,13,14,15,16,17,18,19 \
    9. ,20,21,22,23,24,25,26,27,28,29 \
    10. ,30,31,32,33,34,35,36,37,38,39 \
    11. };
    12. SimpleGraph::SimpleGraph(const GRAPH_ADJARRAY_VECTOR adjgraph)
    13. :m_srcAdjArray(adjgraph)
    14. {
    15. adjArray2adjList(m_srcAdjArray,m_dstAdjList);
    16. }
    17. void SimpleGraph::adjArray2adjList(const GRAPH_ADJARRAY_VECTOR &srcAdjArray, GRAPH_ADJLIST_MAP &dstAdjList)
    18. {
    19. int ncount;
    20. assert( srcAdjArray.size() < MAXVERTEX);
    21. for (int i = 0; i < srcAdjArray.size(); ++i){
    22. ADJPOINTSSET s;
    23. ncount = 0;
    24. for(int j= 0; j< srcAdjArray[i].size(); ++j)
    25. {
    26. if(srcAdjArray[i][j] != 0)
    27. {
    28. s.insert(j + globalOffset[i]);
    29. ncount ++;
    30. }
    31. }
    32. ADJPOINTSPAIR adjPointsPair(ncount,s);
    33. dstAdjList.insert(make_pair(i,adjPointsPair));
    34. }
    35. GRAPH_ADJLIST_MAP::iterator it;
    36. for(it = m_dstAdjList.begin(); it != m_dstAdjList.end(); it++)
    37. {
    38. ADJPOINTSSET s = it->second.second;
    39. ADJPOINTSSET::iterator adjset_it;
    40. for(adjset_it = s.begin(); adjset_it != s.end(); adjset_it++) {
    41. if(*adjset_it > it->first)
    42. {
    43. inc(*adjset_it, it->first);
    44. }
    45. }
    46. }
    47. }
    48. VERTEXCOVER SimpleGraph::getVertexCover()
    49. {
    50. VERTEXCOVER s;
    51. ADJPOINTSSET tmps;
    52. ADJPOINTSSET::iterator adjset_it;
    53. #if PRINTINFO
    54. std::cout << "====================================================" << std::endl;
    55. std::cout << "v d s" << std::endl;
    56. std::cout << "-----" << std::endl;
    57. print();
    58. #endif
    59. //1.put the highest degree vertex in the cover set
    60. GRAPH_ADJLIST_MAP::iterator it, it_target;
    61. while (1) {
    62. #if PRINTINFO
    63. std::cout << "step1.put the highest degree vertex in the cover set" << std::endl;
    64. #endif
    65. int nMaxDegree = 0;
    66. it_target = m_dstAdjList.begin();
    67. for(it = m_dstAdjList.begin(); it != m_dstAdjList.end(); it++)
    68. {
    69. // cout << it->first << " " << it->second.first << endl;
    70. if(nMaxDegree < it->second.first)
    71. {
    72. nMaxDegree = it->second.first;
    73. it_target = it;
    74. }
    75. }
    76. #if PRINTINFO
    77. std::cout << "it_target is " << it_target->first << " " << it_target->second.first << std::endl;
    78. #endif
    79. if(it_target->second.first == 0) break;
    80. s.insert(it_target->first);
    81. #if PRINTINFO
    82. std::cout << "one of highest degree vertex is vertex: " << it_target->first << std::endl;
    83. SimpleGraph::printVertexSet(s);
    84. std::cout << "step2.update the degree of vertexes in the list.if 0, remove it." << std::endl;
    85. #endif
    86. //2.update the degree of vertexes in the list.if 0, remove it.
    87. tmps= it_target->second.second;
    88. for(adjset_it = tmps.begin(); adjset_it != tmps.end(); adjset_it++) {
    89. dec(*adjset_it, it_target->first);
    90. }
    91. it_target->second.first = 0;
    92. it_target->second.second.clear();
    93. #if PRINTINFO
    94. SimpleGraph::print();
    95. #endif
    96. }
    97. m_dstAdjList.clear();
    98. adjArray2adjList(m_srcAdjArray,m_dstAdjList); //restore m_dstAdjList
    99. #if PRINTINFO
    100. std::cout << "step3.Exit the loop,get the one of cover set" << std::endl;
    101. #endif
    102. return s;
    103. }
    104. bool SimpleGraph::checkIsCover(std::vector<int> &vertexSet)
    105. {
    106. bool bret = false;
    107. int n = 1;
    108. ADJPOINTSSET tmps;
    109. ADJPOINTSSET::iterator adjset_it;
    110. //1.put the highest degree vertex in the cover set
    111. GRAPH_ADJLIST_MAP::iterator it, it_target;
    112. std::vector<int>::iterator vit;
    113. int nMaxDegree = 0;
    114. it_target = m_dstAdjList.begin();
    115. vit = vertexSet.begin();
    116. for (vit = vertexSet.begin(); vit != vertexSet.end(); vit++)
    117. {
    118. for(it = m_dstAdjList.begin(); it != m_dstAdjList.end(); it++)
    119. {
    120. // cout << it->first << " " << it->second.first << endl;
    121. if(*vit == it->first + 1)
    122. {
    123. it_target = it;
    124. }
    125. }
    126. tmps= it_target->second.second;
    127. for(adjset_it = tmps.begin(); adjset_it != tmps.end(); adjset_it++) {
    128. dec(*adjset_it, it_target->first);
    129. }
    130. it_target->second.first = 0;
    131. it_target->second.second.clear();
    132. }
    133. for(it = m_dstAdjList.begin(); it != m_dstAdjList.end(); it++)
    134. {
    135. if(it->second.first != 0)
    136. {
    137. n = 0;
    138. break;
    139. }
    140. }
    141. m_dstAdjList.clear();
    142. adjArray2adjList(m_srcAdjArray,m_dstAdjList); //restore m_dstAdjList
    143. if (n == 1) bret = true;
    144. return bret;
    145. }
    146. void SimpleGraph::help()
    147. {
    148. if(m_srcAdjArray.size() == 0)
    149. {
    150. std::cout << "Adjacency Array vector is null\n";
    151. return;
    152. }
    153. int i = 0;
    154. for (auto& line : m_srcAdjArray) {
    155. for (int j=0; j< i; j++) {
    156. std::cout << " ";
    157. }
    158. for (const auto& v : line) {
    159. std::cout << v << " ";
    160. }
    161. std::cout << std::endl;
    162. i++;
    163. }
    164. }
    165. void SimpleGraph::printVertexSet(VERTEXCOVER s)
    166. {
    167. #if 1
    168. ADJPOINTSSET::iterator adjset_it;
    169. std::cout << "{";
    170. for(adjset_it = s.begin(); adjset_it != s.end(); adjset_it++) {
    171. std::cout << *adjset_it << " ";
    172. }
    173. std::cout << "}" << std::endl;
    174. #endif
    175. }
    176. void SimpleGraph::print()
    177. {
    178. #if 1
    179. GRAPH_ADJLIST_MAP::iterator it;
    180. for(it = m_dstAdjList.begin(); it != m_dstAdjList.end(); it++)
    181. {
    182. //输出Node的key值,度数值 和相邻顶点集合
    183. std::cout << it->first << " " << it->second.first << " ";
    184. SimpleGraph::printVertexSet(it->second.second);
    185. }
    186. #endif
    187. }
    188. void SimpleGraph::inc(int keyVertex, int targetVertex)
    189. {
    190. m_dstAdjList.at(keyVertex).first += 1;
    191. m_dstAdjList.at(keyVertex).second.insert(targetVertex);
    192. }
    193. void SimpleGraph::dec(int keyVertex, int targetVertex)
    194. {
    195. m_dstAdjList.at(keyVertex).first -= 1;
    196. m_dstAdjList.at(keyVertex).second.erase(targetVertex);
    197. }
    198. std::vectorint> > SimpleGraph::getCombineNK(int n, int k)
    199. {
    200. std::vector<int> nums = std::vector<int>();
    201. for(int i = 1; i < k + 1 ; ++i)
    202. nums.push_back(i);
    203. nums.push_back(n + 1);
    204. std::vectorint>> retvv = std::vectorint>>();
    205. int j = 0;
    206. while (j < k) {
    207. retvv.push_back(std::vector<int>(nums.begin(), nums.begin() + k));
    208. j = 0;
    209. while ((j < k) && (nums[j + 1] == nums[j] + 1))
    210. {
    211. nums[j] = j + 1;
    212. j++;
    213. }
    214. nums[j] ++ ;
    215. }
    216. return retvv;
    217. }
    218. void SimpleGraph::showCombinationvector( std::vectorint> > va )
    219. {
    220. std::cout << "C(N,K) = " << va.size() << "\n";
    221. std::cout << "[ \n";
    222. for (int var = 0; var < va.size(); ++var) {
    223. std::cout << " [ ";
    224. for(int j=0; j< va[var].size();j++)
    225. {
    226. std::cout << va[var][j] - 1 << " ";
    227. }
    228. std::cout << "]\n";
    229. }
    230. std::cout << "]\n";
    231. }
    1. #include "simplegraph.h"
    2. #include "cprecisetimer.h"
    3. //using namespace std;
    4. int main(int argc, char *argv[])
    5. {
    6. // const int N = 5;
    7. // /*
    8. // (0)--(1)--(2)
    9. // | / \ |
    10. // | / \ |
    11. // | / \ |
    12. // (3)-------(4)
    13. // */
    14. // GRAPH_ADJARRAY_VECTOR graph = {
    15. // {0, 1, 0, 1, 0},
    16. // {0, 1, 1, 1},
    17. // {0, 0, 1},
    18. // {0, 1},
    19. // {0}
    20. // };
    21. // const int N = 6;
    22. // /*
    23. // (0)--(1)--(2)
    24. // | / \ | \
    25. // | / \ | \
    26. // | / \ | \
    27. // (3)-------(4)--(5)
    28. // */
    29. // GRAPH_ADJARRAY_VECTOR graph = {
    30. // {0, 1, 0, 1, 0, 0},
    31. // {0, 1, 1, 1, 0},
    32. // {0, 0, 1, 1},
    33. // {0, 1, 0},
    34. // {0, 1},
    35. // {0}
    36. // };
    37. const int N = 30;
    38. GRAPH_ADJARRAY_VECTOR graph = {
    39. {0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0},
    40. {0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0},
    41. {0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0},
    42. {0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0},
    43. {0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0},
    44. {0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0},
    45. {0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0},
    46. {0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0},
    47. {0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0},
    48. {0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0},
    49. {0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0},
    50. {0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0},
    51. {0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0},
    52. {0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0},
    53. {0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0},
    54. {0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0},
    55. {0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1},
    56. {0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0},
    57. {0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1},
    58. {0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0},
    59. {0, 1, 0, 1, 0, 0, 1, 0, 1, 0},
    60. {0, 1, 1, 1, 0, 1, 0, 1, 0},
    61. {0, 1, 0, 1, 0, 0, 1, 0},
    62. {0, 1, 1, 1, 0, 1, 0},
    63. {0, 1, 0, 1, 0, 0},
    64. {0, 1, 1, 1, 0},
    65. {0, 0, 1, 1},
    66. {0, 1, 0},
    67. {0, 1},
    68. {0}
    69. };
    70. CPreciseTimer preciseTimer;
    71. std::cout << "G Upper Triangle Matrix" << std::endl;
    72. SimpleGraph G(graph);
    73. G.help();
    74. std::cout << "Computing Min Vertex Cover..." << std::endl;
    75. VERTEXCOVER coverSet = G.getVertexCover();
    76. std::cout << "Print Min Vertex Cover..." << std::endl;
    77. SimpleGraph::printVertexSet(coverSet);
    78. int k= coverSet.size();
    79. std::cout << "cover vertex number should be:" << k << std::endl;
    80. std::vectorint>> va = SimpleGraph::getCombineNK(N,k);
    81. SimpleGraph::showCombinationvector(va);
    82. std::vectorint>> allCover;
    83. preciseTimer.StartTimer();
    84. for (int index = 0; index < va.size(); ++index) {
    85. bool bIsCover = G.checkIsCover(va[index]);
    86. if(bIsCover) {
    87. allCover.push_back(va[index]);
    88. }
    89. }
    90. preciseTimer.StopTimer();
    91. __int64 timeElasps = preciseTimer.GetTime();
    92. std::cout << "time elapse is " << timeElasps << " microseonds" << std::endl;
    93. std::cout << "all cover set is as follows!!!" << std::endl;
    94. SimpleGraph::showCombinationvector(allCover);
    95. std::cout << "Finish!!!" << std::endl;
    96. }

  • 相关阅读:
    LeetCode 1004.最大连续1的个数
    MySQL最大建议行数2000w, 靠谱吗?
    First SP800-140Br1 Compliant FIPS 140-3 Certificates
    SSM总结
    程序人生 | 编程的上帝视角应该怎么去找
    CentOS 8 正式停服;复旦教授痛批 Google 修复高危漏洞一直延期;WebStorm 2021.3.1 发布 | 开源日报
    文心一言 VS 讯飞星火 VS chatgpt (102)-- 算法导论9.3 8题
    【暗月安全】2021年渗透测试全套培训视频
    NR 2-STEP RA Absolute Timing Advance Command MAC CE的应用场景
    一文学会MyBatis的使用~
  • 原文地址:https://blog.csdn.net/zkmrobot/article/details/133832449