题意:给定简单无向图,求一个最小的边集使得这些点是边双,输出方案。n <= 14

解:考虑一个边双肯定是一条一条的链拼起来的。于是每次枚举一条链加上去就行了。

设fs表示点集s形成边双的最小边数。linki,j,s表示点集s能否形成一个i - j的链。link2x,s表示点x和点集s是否直接相连。

上面这些数组都要记录方案,特别地,link2要记录两个方案,为了应对拼上去的链退化成一个点的情况。

  1. #include <bits/stdc++.h>
  2.  
  3. const int N = ;
  4.  
  5. struct Edge {
  6. int nex, v;
  7. }edge[N << ]; int tp;
  8.  
  9. struct Node {
  10. int x, y, t;
  11. Node(int X = , int Y = , int T = ) {
  12. x = X;
  13. y = Y;
  14. t = T;
  15. }
  16. }fr3[N];
  17.  
  18. int pw[N], cnt[N], f[N], e[N], n, m;
  19. bool link[][][N], link2[][N];
  20. int fr[][][N], fr2[][N], fr22[][N];
  21.  
  22. inline void add(int x, int y) {
  23. tp++;
  24. edge[tp].v = y;
  25. edge[tp].nex = e[x];
  26. e[x] = tp;
  27. return;
  28. }
  29.  
  30. void out(int x, int y, int s) {
  31. if(cnt[s] == ) return;
  32. printf("%d %d \n", y + , fr[x][y][s]);
  33. out(x, fr[x][y][s] - , s ^ ( << y));
  34. return;
  35. }
  36.  
  37. void out3(int s) {
  38. if(cnt[s] == ) return;
  39. int x = fr3[s].x, y = fr3[s].y, t = fr3[s].t;
  40. out(x, y, t);
  41. printf("%d %d \n", x + , fr2[x][s ^ t]);
  42. if(x != y) printf("%d %d \n", y + , fr2[y][s ^ t]);
  43. else printf("%d %d \n", y + , fr22[y][s ^ t]);
  44. out3(s ^ t);
  45. return;
  46. }
  47.  
  48. int main() {
  49. scanf("%d%d", &n, &m);
  50. for(int i = , x, y; i <= m; i++) {
  51. scanf("%d%d", &x, &y);
  52. add(x, y);
  53. add(y, x);
  54. }
  55. int lm = ( << n) - ; /// lm = 111111...1
  56. for(int i = ; i <= lm; i++) {
  57. cnt[i] = + cnt[i - (i & (-i))];
  58. if(i > ) pw[i] = pw[i >> ] + ;
  59. }
  60.  
  61. for(int x = ; x < n; x++) {
  62. for(int s = ; s <= lm; s++) {
  63. /// link2[x][s]
  64. if((s >> x) & ) continue;
  65. for(int i = e[x + ]; i; i = edge[i].nex) {
  66. int y = edge[i].v - ;
  67. if((s >> y) & ) {
  68. link2[x][s] = ;
  69. if(!fr2[x][s]) {
  70. fr2[x][s] = y + ;
  71. }
  72. else {
  73. fr22[x][s] = y + ;
  74. break;
  75. }
  76. }
  77. }
  78. }
  79. }
  80.  
  81. for(int i = ; i < n; i++) {
  82. link[i][i][ << i] = ;
  83. }
  84. for(int s = ; s < lm; s++) {
  85. for(int t1 = s, i; t1; t1 ^= ( << i)) {
  86. i = pw[t1 & (-t1)];
  87. /// i + 1
  88. for(int t2 = s, x; t2; t2 ^= ( << x)) {
  89. x = pw[t2 & (-t2)];
  90. /// f[i][x][s]
  91. if(!link[i][x][s]) continue;
  92. for(int j = e[x + ]; j; j = edge[j].nex) {
  93. int y = edge[j].v - ;
  94. if(((s >> y) & ) == ) {
  95. link[i][y][s | ( << y)] = ;
  96. fr[i][y][s | ( << y)] = x + ;
  97. }
  98. }
  99. }
  100. }
  101. }
  102.  
  103. memset(f, 0x3f, sizeof(f));
  104. f[] = ;
  105. for(int s = ; s <= lm; s++) {
  106. /// f[s]
  107. for(int t = s & (s - ); t; t = (t - ) & s) {
  108. for(int t1 = t, x; t1; t1 ^= ( << x)) {
  109. x = pw[t1 & (-t1)];
  110. for(int t2 = t, y; t2; t2 ^= ( << y)) {
  111. y = pw[t2 & (-t2)];
  112. /// link[x][y][t] link2[x][s ^ t] link2[y][s ^ t]
  113. if(link[x][y][t] && link2[x][s ^ t] && link2[y][s ^ t] && (x != y || fr22[x][s ^ t])) {
  114. if(f[s] > f[s ^ t] + cnt[t] + ) {
  115. f[s] = f[s ^ t] + cnt[t] + ;
  116. fr3[s] = Node(x, y, t);
  117. }
  118. }
  119. }
  120. }
  121. }
  122. }
  123.  
  124. printf("%d\n", f[lm]);
  125. out3(lm);
  126. return ;
  127. }

AC代码

CF1155F Delivery Oligopoly的更多相关文章

  1. Codeforces 1155F Delivery Oligopoly dp(看题解)

    看别人写的才学会的... 我们考虑刚开始的一个点, 然后我们枚举接上去的一条一条链, dp[mask]表示当前已经加进去点的状态是mask所需的最少边数. 反正就是很麻烦的一道题, 让我自己写我是写不 ...

  2. 【Virt.Contest】CF1155(div.2)

    CF 传送门 T1:Reverse a Substring 只有本身单调不减的字符串不能转换为字典序更小的字符串.否则肯定会出现 \(s_i>s_{i+1}\) 的情况. 所以只要从头到尾扫一遍 ...

  3. 《Continuous Delivery》 Notes 1: The problem of delivering software

    What is "Deployment pipeline"? A deployment pipeline is an automated implementation of you ...

  4. zoj 3469 Food Delivery 区间dp + 提前计算费用

    Time Limit: 2 Seconds      Memory Limit: 65536 KB When we are focusing on solving problems, we usual ...

  5. 【IOS笔记】Event Delivery: The Responder Chain

    Event Delivery: The Responder Chain  事件分发--响应链 When you design your app, it’s likely that you want t ...

  6. Content Delivery Network

    Coding Standards & Best Practices 7 Reasons to use a Content Delivery Network CDN公共库汇总

  7. codeforces 653D D. Delivery Bears(二分+网络流)

    题目链接: D. Delivery Bears time limit per test 2 seconds memory limit per test 256 megabytes input stan ...

  8. zoj 3742 Delivery 好题

    Delivery 题目还是自己看吧 - -! 看似图论,实际上是一个考察思维以及数据结构的题. 我们对于先前和向后的边分别进行统计. 对询问离线. 小边按照左端点从大到小排序. 1.对于向后的边,询问 ...

  9. Repost: Set Delivery Block on SO

    If SO is incomplete, then automatically set the delivery block on the SO header. as suggested by ear ...

随机推荐

  1. Poj1477

    Box of Bricks Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 24101   Accepted: 9378 De ...

  2. 禁用事件event默认行为

    在大多数情况下,为事件处理函数返回false,可以防止默认的事件行为.例如,默认情况下点击一个<a>元素,页面会跳转到该元素href属性指定的页. js中return false作用一般是 ...

  3. App隐私条款

    欢迎光临本app,请您仔细阅读以下条款,如果您对本协议的任何条款表示异议,您可以选择不使用本app:进入本app则意味着您将同意遵守本协议下全部规定,并完全服从于app开发者的统一管理. 第一章 总则 ...

  4. django 问题综合

    orm部分 本篇文章我会持续更新,把开发中遇到的一切orm相关的问题都放在这里 mysql索引报错 使用django 的orm,数据库用的mysql,在使用makemigrations和migrate ...

  5. Linux/Ubuntu 16.04 安装编辑器 Sublime Text 3

    在ubuntu 16.04 系统上使用Sublime Text 3 编辑文本还是不错的, 先到官网下载安装包,链接:http://www.sublimetext.com/3 ,下载对应的版本,64位或 ...

  6. LeetCode算法题-Largest Number At Least Twice of Others(Java实现)

    这是悦乐书的第308次更新,第328篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第177题(顺位题号是747).在给定的整数数组中,总有一个最大的元素.查找数组中的最大 ...

  7. #032 有空就看PTA

      我咋买书了? 上学期

  8. 【java学习】Intelli Idea集成开发工具的使用

    == mac版直接下载地址: https://download.jetbrains.com/idea/ideaIU-2018.1.6.dmg   ==mac配置java环境变量: https://ji ...

  9. 安装Linux虚拟系统

    VMWare创建虚拟机与Linux系统的安装 准备工作:VMWare虚拟机,Linux系统镜像 创建好虚拟机之后就可以进入Bios(Basic input ouput system)界面设置安装引导顺 ...

  10. 蚂蚁 uva 10881

    思路: 一,两个点相撞然后,相互弹开.这样其实和两个点穿过去差不多, 但是对于单个点而言,这样肯定不行. 二,当你发现了不管什么情况,这些点的相对位置是不变的, 比如 1, 4, 3, 2 不管怎么移 ...