有向图输出所有环,相同的环仅输出字典序最小的序列

﹏ヽ暗。殇╰゛Y 2023-07-13 13:53 45阅读 0赞

注释超级详细。。不信你看不懂。。看不懂底下留言!!!!

数据输入

该有向图用链式图存储

a b;a c;b e;e b;c d;d a

20200312172327381.png

运行结果

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zODE5OTc3MA_size_16_color_FFFFFF_t_70

  1. #include<iostream>
  2. #include<string>
  3. #include<map>
  4. #include<vector>
  5. #include<algorithm>
  6. #include<set>
  7. using namespace std;
  8. //有向图中找出所有的环,重复的环只保留字典序最小的序列:比如abcda,bcdab是同一个环,只保留abcda
  9. /*
  10. set<char>s;是用来记录哪些元素构成环 (set具有不重复性)
  11. set<set<char> >set_circle_element;用来存储每个环的元素,
  12. 当有一个新环被发现,就被加入到里面。同时这保证了相同环的最小字典序.
  13. 比如发现有一个环是abcda,set_circle_element就记录了{a,b,c,d}。当发现bcdab这个环时,
  14. 因为set_circle_element中已经有 {a,b,c,d}了,就不考虑bcdab这个环了。同理cdbac...
  15. vector<vector<char> >CIRCLE;用来存储存储字典序最小的环
  16. */
  17. vector<char>expend;
  18. vector<char>circle;//记录每次的序列,是最小字典序的环就加入到 vector<vector<char> >CIRCLE中
  19. vector<vector<char> >EXPAND;
  20. vector<vector<char> >CIRCLE;
  21. map<char,vector<char> >mp;//链式图
  22. set<char>s;
  23. set<set<char> >set_circle_element;
  24. //
  25. /*
  26. 比较函数
  27. vector元素小的排前面
  28. 要是两个vector一样大,就选字典序小的排前面
  29. */
  30. int cmp(vector<char>a,vector<char>b)
  31. {
  32. if(a.size()!=b.size())
  33. return a.size()<b.size();
  34. else
  35. {
  36. vector<char>::iterator it1,it2;
  37. for(it1=a.begin(),it2=b.begin();it1!=a.end();it1++,it2++)
  38. if((*it1)!=(*it2))
  39. return (*it1)<(*it2);
  40. else
  41. continue;
  42. return 1;
  43. }
  44. }
  45. //打印序列
  46. void show()
  47. {
  48. vector<char>::iterator it2;
  49. for(it2=circle.begin();it2!=circle.end();it2++)
  50. {
  51. cout<<(*it2)<<" ";
  52. }
  53. cout<<endl;
  54. }
  55. void dfs(char start)
  56. {
  57. //递归终点1
  58. //s发现有重复元素说明出现了环,并且判断这个新字符是否和circle序列第一个元素相等
  59. if(s.find(start)!=s.end()&& start==*circle.begin())
  60. {
  61. circle.push_back(start);//circle加入新元素,此时circle是一个环
  62. /*
  63. //判断s在set_circle_element中是否出现过,
  64. 如果出现过,说明此时的circle不是最小字典序,就不用添加了,否则添加
  65. */
  66. if(set_circle_element.find(s)==set_circle_element.end() )
  67. {
  68. set_circle_element.insert(s);//添加新的元素组合
  69. CIRCLE.push_back(circle);//添加一个新的字典序最小的环
  70. }
  71. return ;
  72. }
  73. //递归终点2
  74. /*
  75. 如果这个新的元素start在circle中出现过说明此时start在circle的中间且不是第一个(因为递归终点1已经判断过了),
  76. 要是再加入这个元素,会在circle序列中产生子环(abcdc),这是不允许的,所以return
  77. */
  78. vector<char>::iterator ret;
  79. ret=find(circle.begin(), circle.end(), start);
  80. if(ret!=circle.end())
  81. return;
  82. //递归终点3 :序列的长度都大于结点个数了,必须return
  83. if(circle.size()>mp.size())
  84. return;
  85. //这个start不符合上面三个递归终点,将其加入circle序列和s集合
  86. s.insert(start);//s加入start
  87. circle.push_back(start);//circle加入start
  88. vector<char>::iterator it;
  89. char next;
  90. //用链式图(变量名为mp)索引为start的vector数组元素依次作为序列的下一个元素
  91. for(it=mp[start].begin();it!=mp[start].end();it++)
  92. {
  93. next=(*it);
  94. dfs(next);
  95. }
  96. //这两条语句是为了恢复现场,恢复成没加入start的情形
  97. circle.pop_back();
  98. s.erase(start);
  99. }
  100. int main()
  101. {
  102. freopen("1.txt","r",stdin);
  103. char c1,c2;
  104. //构建链式图,此处因为每个人读入数据的格式不一样,需要自己修改
  105. while(cin>>c1>>c2)
  106. {
  107. getchar();
  108. mp[c1].push_back(c2);
  109. //du[c2]++;
  110. s.insert(c2);
  111. }
  112. map<char,vector<char> >::iterator it;
  113. //输出链式图
  114. cout<<"输出链式图"<<endl;
  115. for(it=mp.begin();it!=mp.end();it++)
  116. {
  117. char start=(*it).first;
  118. cout<<start<<":";
  119. vector<char>::iterator it2;
  120. for(it2=(*it).second.begin();it2!=(*it).second.end();it2++)
  121. {
  122. cout<<(*it2)<<" ";
  123. }
  124. cout<<endl;
  125. }
  126. /*
  127. 遍历链式图的每个结点,并用每个结点连接的元素作为
  128. */
  129. s.clear();
  130. for(it=mp.begin();it!=mp.end();it++)//遍历链式图的每个结点
  131. {
  132. char start=(*it).first;//获取第一个结点
  133. vector<char>::iterator it2;
  134. for(it2=(*it).second.begin();it2!=(*it).second.end();it2++)//并用每个结点连接的元素(vector)作为下一个元素
  135. {
  136. //每次换新元素时都要重新把start加入,因为dfs之后会把s和circle清空
  137. circle.push_back(start);
  138. s.insert(start);
  139. dfs(*it2);//(*it2就是vector数组中的每个元素)开始递归。。。
  140. //恢复现场,为下一个vector中的元素充当circle序列中start之后的元素做准备
  141. s.clear();
  142. circle.clear();
  143. }
  144. //恢复现场,感觉这两句多余,但是为了保险,还是清除一下吧
  145. s.clear();
  146. circle.clear();
  147. }
  148. cout<<"打印所有环"<<endl;
  149. sort(CIRCLE.begin(),CIRCLE.end(),cmp);//给 CIRCLE排序
  150. //打印 CIRCLE,每个人的打印方式不一样,自己修改
  151. vector<vector<char> >::iterator it1;
  152. vector<char>::iterator it2;
  153. for(it1=CIRCLE.begin();it1!=CIRCLE.end();it1++)
  154. {
  155. for(it2=(*it1).begin();it2!=(*it1).end();it2++)
  156. {
  157. cout<<(*it2)<<" ";
  158. }
  159. cout<<";";
  160. }
  161. return 0;
  162. }

发表评论

表情:
评论列表 (有 0 条评论,45人围观)

还没有评论,来说两句吧...

相关阅读

    相关 (3)--寻找

    在和有向图相关的实际应用中,有向环特别重要。 从原则上来说,一幅有向图可能含有大量的环,在实际应用中,我们一般只会重点关注其中一小部分,或者只想知道它们是否存在。 思路:一