如果要相邻两个数(a[i] >= 2)相加为质数,显然它们的奇偶性不同,也就是说一个圆桌(环)必须是偶环。

也就是答案的若干个环组成了一张二分图,其中以奇偶分色。

考虑每个点的度数一定为2,用最大流解决:

  1. 让源点向所有的奇数点连流量为2的边。
  2. 让所有的偶数点向汇点连流量为2的边。
  3. 当且仅当一组奇数和偶数相加为质数时,连一条流量为1的边。

可以证明,如果最大流小于n,那就不存在解,否则一定存在若干个边数大于2的偶环,使得所有点只出现在一个环里,最后Dfs找出环即可。

$ \bigodot $ 技巧&套路:

  • 根据奇偶性或网格图黑白染色,想到建立二分图。
  • 最大流的模型。
  1. #include <cstdio>
  2. #include <vector>
  3. #include <cstring>
  4. #include <algorithm>
  5.  
  6. const int N = , M = ;
  7.  
  8. int n, s, t, tot, a[N], vis[N], lc[N], rc[N], ln, rn;
  9. int ntp[];
  10. std::vector<int> an[N];
  11.  
  12. void Init() {
  13. ntp[] = ;
  14. for (int i = ; i <= ; ++i) if (!ntp[i]) {
  15. for (int j = i * i; j <= ; j += i) {
  16. ntp[j] = ;
  17. }
  18. }
  19. }
  20.  
  21. namespace GR {
  22. int yun = , cur[N], las[N], to[M << ], pre[M << ], fl[M << ];
  23. int h[N], gap[N];
  24. inline void Add(int a, int b, int c) {
  25. to[++yun] = b; fl[yun] = c; pre[yun] = las[a]; las[a] = yun;
  26. to[++yun] = a; fl[yun] = ; pre[yun] = las[b]; las[b] = yun;
  27. }
  28. int Isap(int x, int flo, int usd = ) {
  29. if (x == t) return flo;
  30. for (int i = cur[x]; i; i = pre[i]) if (fl[i] > && h[to[i]] + == h[x]) {
  31. int f = Isap(to[i], std::min(flo, fl[i]));
  32. usd += f; fl[i] -= f; fl[i ^ ] += f;
  33. if (fl[i] > ) cur[x] = i;
  34. if (usd == flo) return flo;
  35. }
  36. if (gap[h[x]] == ) h[s] = t + ;
  37. --gap[h[x]]; ++gap[++h[x]];
  38. cur[x] = las[x];
  39. return usd;
  40. }
  41. int Max_flow(int re = ) {
  42. memset(h, , sizeof h);
  43. memset(gap, , sizeof gap);
  44. for (; h[s] < t + ; ) re += Isap(s, 1e9);
  45. return re;
  46. }
  47. }
  48.  
  49. void Build() {
  50. s = n + ; t = n + ;
  51. for (int i = ; i <= n; ++i) {
  52. if (a[i] & ) {
  53. lc[++ln] = i; GR::Add(s, i, );
  54. } else {
  55. rc[++rn] = i; GR::Add(i, t, );
  56. }
  57. }
  58. for (int i = ; i <= ln; ++i) {
  59. for (int j = ; j <= rn; ++j) {
  60. if (!ntp[a[lc[i]] + a[rc[j]]]) {
  61. GR::Add(lc[i], rc[j], );
  62. }
  63. }
  64. }
  65. }
  66.  
  67. void Dfs(int gr, int x) {
  68. an[gr].push_back(x);
  69. vis[x] = ;
  70. for (int i = GR::las[x]; i; i = GR::pre[i]) {
  71. int v = GR::to[i];
  72. if (vis[v] || v == s || v == t) continue;
  73. if (((~i & ) && GR::fl[i] == ) || ((i & ) && GR::fl[i] == )) {
  74. Dfs(gr, v);
  75. }
  76. }
  77. }
  78.  
  79. int main() {
  80. Init();
  81. scanf("%d", &n);
  82. for (int i = ; i <= n; ++i) {
  83. scanf("%d", &a[i]);
  84. }
  85. Build();
  86.  
  87. int ans = GR::Max_flow();
  88. if (ans != n) {
  89. puts("Impossible"); return ;
  90. }
  91. for (int i = ; i <= n; ++i) {
  92. if (!vis[i]) Dfs(++tot, i);
  93. }
  94. printf("%d\n", tot);
  95. for (int i = ; i <= tot; ++i) {
  96. printf("%d ", (int)an[i].size());
  97. for (int j = ; j < (int)an[i].size(); ++j) {
  98. printf("%d ", an[i][j]);
  99. }
  100. putchar('\n');
  101. }
  102.  
  103. return ;
  104. }

【Cf #290 C】Fox And Dinner(最大流)的更多相关文章

  1. Solution -「CF 510E」Fox And Dinner

    \(\mathcal{Description}\)   Link.   给定正整数集合 \(\{a_n\}\),求一种把这些数放置在任意多个圆环上的方案,使得每个环的大小大于 \(2\) 且环上相邻两 ...

  2. Codeforces Round #290 (Div. 2) E. Fox And Dinner 网络流建模

    E. Fox And Dinner time limit per test 2 seconds memory limit per test 256 megabytes input standard i ...

  3. CF510E. Fox And Dinner

    CF510E. Fox And Dinner https://codeforces.com/contest/510 分析: 由于\(a_i>2\), 相邻两个数一定一奇一偶,按奇偶建立二分图. ...

  4. [CF#290 Div.1 C]Fox And Dinner(最大流)

    题目:http://codeforces.com/contest/512/problem/C 题目大意:给你若干个数,让你分成k组,每组围成一个圆,使得相邻两个数和均为素数,且每组人数应>=3个 ...

  5. 网络流(最大流)CodeForces 512C:Fox And Dinner

    Fox Ciel is participating in a party in Prime Kingdom. There are n foxes there (include Fox Ciel). T ...

  6. CodeForces Round #290 Fox And Dinner

    而是Div2的最后一题,当时打比赛的时候还不会最大流.自己能够把它写出来然后1A还是很开心的. 题意: 有n个不小于2的整数,现在要把他们分成若干个圈.在每个圈中,数字的个数不少于3个,而且相邻的两个 ...

  7. Fox And Dinner CodeForces - 510E (最大流)

    大意: n只狐狸, 要求分成若干个环, 每个环的狐狸不少于三只, 相邻狐狸年龄和为素数. 狐狸年龄都>=2, 那么素数一定为奇数, 相邻必须是一奇一偶, 也就是一个二分图, 源点向奇数点连容量为 ...

  8. 【Cf #290 B】Fox And Jumping(dp,扩展gcd)

    根据裴蜀定理,当且仅当选出来的集合的L[i]的gcd等于1时,才能表示任何数. 考虑普通的dp,dp[i][j]表示前i个数gcd为j的最少花费,j比较大,但状态数不多,拿个map转移就好了. $ \ ...

  9. 网络流 I - Fox And Dinner CodeForces - 510E

    Fox Ciel is participating in a party in Prime Kingdom. There are n foxes there (include Fox Ciel). T ...

随机推荐

  1. Windows ,获取硬盘物理序列号(VC++)

    #include <windows.h> BOOL GetHDID(PCHAR pIDBufer) {     HANDLE hDevice=NULL;    hDevice=::Crea ...

  2. python—多任务版udp聊天机器人

    将多任务(多线程)引入到udp聊天机器人,可以实现同时发送消息和接收消息 import socket import threading def udp_send(udp_socket,ip,port) ...

  3. Swagger本地环境配置

    一.技术背景 随着互联网技术的发展,现在的网站架构基本都由原来的后端渲染,变成了:前端渲染.先后端分离的形态,而且前端技术和后端技术在各自的道路上越走越远.而前后端的唯一联系便是 API 接口,与此同 ...

  4. 将React Native 集成进现有OC项目中(过程记录) 、jsCodeLocation 生成方式总结

    将RN集成到现有OC项目应该是最常见的,特别是已经有OC项目的,不太可能会去专门搞个纯RN的项目.又因为RN不同版本,引用的依赖可能不尽相同,所以特别说明下,本文参考的文档是React Native ...

  5. 如何使用g++编译调用dll的c++代码

    本文将有以下4个部分来讲如何使用g++编译调用dll的c++代码. 1.如何调用dll 2.动态链接和静态链接的区别 3.g++的编译参数以及如何编译调用dll的c++代码 4.总结 1.如何调用dl ...

  6. Beta发布--PSP DAILY软件功能说明书2.0

    一.开发背景 你在完成了一周的软件工程作业后,需要提交一个PSP图表,里面有4项,如下所示: 1.本周PSP表格,包含每项任务的开始.中断.结束.最终时间,格式如下: 2.本周进度条,包含从开始到现在 ...

  7. 1到N中“1”出现的次数

    题目:给定一个十进制的正整数,写下从1开始,到N的所有整数,然后数一下其中出现“1”的个数 思路:刚开始做的时候,是想从1到N进行遍历,其中每个数都出现1的个数加起来,最后得出结果,但是老师让我们找规 ...

  8. System 类的使用

    /*System 系统类 主要用于获取系统的属性数据.System类常用的方法: arraycopy(Object src, int srcPos, Object dest, int destPos, ...

  9. 用JAVA制作微型操作系统4月23日情况

    弄好了一个自认为十分精美的界面,但本想着昨天就在开始按钮上先套入控制jp222面板上的jb2标签上的时间更新,这按钮起到开始线程的作用(我认为按钮应该可以通过t.start()来触发线程,结果不知为什 ...

  10. 第1阶段冲刺成果—简单运算game(APP)

    第1阶段冲刺成果 由于我们团队都没有Android的基础,所以在这一块花了很长的时间去学习探索,就连简单的Android的电脑配置也花了很长的时间,所以其他的DONE的都没有完成,这是失败的地方.但是 ...