Fox Ciel is participating in a party in Prime Kingdom. There are n foxes there (include Fox Ciel). The i-th fox is ai years old.

They will have dinner around some round tables. You want to distribute foxes such that:

  1. Each fox is sitting at some table.
  2. Each table has at least 3 foxes sitting around it.
  3. The sum of ages of any two adjacent foxes around each table should be a prime number.

If k foxes f1f2, ..., fk are sitting around table in clockwise order, then for 1 ≤ i ≤ k - 1: fi and fi + 1 are adjacent, and f1 and fk are also adjacent.

If it is possible to distribute the foxes in the desired manner, find out a way to do that.

Input

The first line contains single integer n (3 ≤ n ≤ 200): the number of foxes in this party.

The second line contains n integers ai (2 ≤ ai ≤ 104).

Output

If it is impossible to do this, output "Impossible".

Otherwise, in the first line output an integer m (): the number of tables.

Then output m lines, each line should start with an integer k -=– the number of foxes around that table, and then k numbers — indices of fox sitting around that table in clockwise order.

If there are several possible arrangements, output any of them.

Examples

Input
  1. 4
    3 4 8 9
Output
  1. 1
    4 1 2 4 3
Input
  1. 5
    2 2 2 2 2
Output
  1. Impossible
Input
  1. 12
    2 3 4 5 6 7 8 9 10 11 12 13
Output
  1. 1
    12 1 2 3 6 5 12 9 8 7 10 11 4
Input
  1. 24
    2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
Output
  1. 3
    6 1 2 3 6 5 4
    10 7 8 9 12 15 14 13 16 11 10
    8 17 18 23 22 19 20 21 24

Note

In example 1, they can sit around one table, their ages are: 3-8-9-4, adjacent sums are: 11, 17, 13 and 7, all those integers are primes.

In example 2, it is not possible: the sum of 2+2 = 4 is not a prime number.

题目大意:

就是有n只狐狸,给了你他们的年龄,让你给他们安排位置,有几个要求,第一个是每一张桌子至少做三只狐狸,第二个是任意两只相邻位子的狐狸他们的年龄之和为一个素数。

让你输出桌子数量,然后输出每一张桌子做的人数和桌子坐了哪些人。

思路:

这个题目我一开始想到了二分图的最大匹配,但是怎么建图都感觉有点问题,然后我就看了题解,感觉题解写的挺巧妙的。

就是因为年龄一定大于等于2,所以年龄之和要是为素数就肯定是一个奇数,所以这个就把奇数和偶数分开。

奇数和偶数分开,这个就很容易想到是网络流,怎么建图我其实还是没有想清楚,继续看题解。

分开之后把奇数和源点相连,偶数和汇点相连,容量都是2.

奇数和偶数如果加和得到一个质数,那么奇数和这个偶数相连,容量为1.

为什么要这么建图呢?因为如果奇数和源点的容量应该是2,如果满流就代表着这个奇数连到了两个偶数而且奇数偶数之和为一个素数,

这个样子就找到了这个奇数左右两边相邻的数,这个样子同时满足了第一第二两个条件。

显而易见如果要满足上面的建图条件,则奇数和偶数一定要相同,因为奇数和源点容量是2,偶数和汇点容量也是2(因为一个偶数两边应该也要两个奇数,奇偶加和为一个素数)

所以这个最大流就应该==n。如果不满足就输出impossible

最后就是路径的输出了,这个用用数组来存,把连了的边存到一个数组里面,用vis进行标记来确定不会连重复的边。

然后就是一个递归来找这个桌子的数量,如果一条边它的容量为1则说明这个被经过,就可以加上这条边。

值得注意的是,这些奇数偶数肯定会形成一个环,所以不用担心可能会导致存在两个相邻的数不满足条件,

这个不确定的话可以自己模拟一下。

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cstring>
  4. #include <string>
  5. #include <queue>
  6. #include <vector>
  7. #include <algorithm>
  8. #define inf 0x3f3f3f3f
  9. using namespace std;
  10. typedef long long ll;
  11. const int maxn = 1e5 + ;
  12. const int INF = 0x3f3f3f3f;
  13. struct edge
  14. {
  15. int u, v, c, f;
  16. edge(int u, int v, int c, int f) :u(u), v(v), c(c), f(f) {}
  17. };
  18. vector<edge>e;
  19. vector<int>G[maxn];
  20. int level[maxn];//BFS分层,表示每个点的层数
  21. int iter[maxn];//当前弧优化
  22. int m;
  23. void init(int n)
  24. {
  25. for (int i = ; i <= n; i++)G[i].clear();
  26. e.clear();
  27. }
  28. void add(int u, int v, int c)
  29. {
  30. e.push_back(edge(u, v, c, ));
  31. e.push_back(edge(v, u, , ));
  32. m = e.size();
  33. G[u].push_back(m - );
  34. G[v].push_back(m - );
  35. }
  36. void BFS(int s)//预处理出level数组
  37. //直接BFS到每个点
  38. {
  39. memset(level, -, sizeof(level));
  40. queue<int>q;
  41. level[s] = ;
  42. q.push(s);
  43. while (!q.empty())
  44. {
  45. int u = q.front();
  46. q.pop();
  47. for (int v = ; v < G[u].size(); v++)
  48. {
  49. edge& now = e[G[u][v]];
  50. if (now.c > now.f && level[now.v] < )
  51. {
  52. level[now.v] = level[u] + ;
  53. q.push(now.v);
  54. }
  55. }
  56. }
  57. }
  58. int dfs(int u, int t, int f)//DFS寻找增广路
  59. {
  60. if (u == t)return f;//已经到达源点,返回流量f
  61. for (int &v = iter[u]; v < G[u].size(); v++)
  62. //这里用iter数组表示每个点目前的弧,这是为了防止在一次寻找增广路的时候,对一些边多次遍历
  63. //在每次找增广路的时候,数组要清空
  64. {
  65. edge &now = e[G[u][v]];
  66. if (now.c - now.f > && level[u] < level[now.v])
  67. //now.c - now.f > 0表示这条路还未满
  68. //level[u] < level[now.v]表示这条路是最短路,一定到达下一层,这就是Dinic算法的思想
  69. {
  70. int d = dfs(now.v, t, min(f, now.c - now.f));
  71. if (d > )
  72. {
  73. now.f += d;//正向边流量加d
  74. e[G[u][v] ^ ].f -= d;
  75. //反向边减d,此处在存储边的时候两条反向边可以通过^操作直接找到
  76. return d;
  77. }
  78. }
  79. }
  80. return ;
  81. }
  82. int Maxflow(int s, int t)
  83. {
  84. int flow = ;
  85. for (;;)
  86. {
  87. BFS(s);
  88. if (level[t] < )return flow;//残余网络中到达不了t,增广路不存在
  89. memset(iter, , sizeof(iter));//清空当前弧数组
  90. int f;//记录增广路的可增加的流量
  91. while ((f = dfs(s, t, INF)) > )
  92. {
  93. flow += f;
  94. }
  95. }
  96. return flow;
  97. }
  98. int p[maxn];
  99. void init()
  100. {
  101. memset(p, , sizeof(p));
  102. for (int i = ; i < maxn; i++) p[i] = ;
  103. for(ll i=;i*i<maxn;i++)
  104. {
  105. if(p[i])
  106. {
  107. for(ll j=i*i;j<maxn;j+=i)
  108. {
  109. p[j] = ;
  110. }
  111. }
  112. }
  113. }
  114. int a[maxn], cnt, out[maxn];
  115. vector<int>vec[maxn];
  116. bool vis[maxn];
  117.  
  118. void solve(int u)
  119. {
  120. out[++cnt] = u;
  121. for(int i=;i<vec[u].size();i++)
  122. {
  123. int v = vec[u][i];
  124. if (vis[v]) continue;
  125. vis[v] = ;
  126. solve(v);
  127. }
  128. }
  129.  
  130. int main()
  131. {
  132. init();
  133. int n;
  134. scanf("%d", &n);
  135. int s = , t = n + ;
  136. for(int i=;i<=n;i++)
  137. {
  138. scanf("%d", &a[i]);
  139. if (a[i] & ) add(s, i, );
  140. else add(i, t, );
  141. }
  142. for(int i=;i<=n;i++)
  143. {
  144. if(a[i]&)
  145. {
  146. for(int j=;j<=n;j++)
  147. {
  148. if (i == j) continue;
  149. if (p[a[i] + a[j]]) add(i, j, );
  150. }
  151. }
  152. }
  153. int ans = Maxflow(s, t);
  154. if(ans!=n)
  155. {
  156. printf("Impossible\n");
  157. return ;
  158. }
  159. for(int i=;i<=n;i++)
  160. {
  161. if(a[i]&)
  162. {
  163. for(int j=;j<G[i].size();j++)
  164. {
  165. edge now = e[G[i][j]];
  166. if(now.v<t&&now.v>s&&now.u<t&&now.u>s&&now.f==)
  167. {
  168. vec[now.u].push_back(now.v);
  169. vec[now.v].push_back(now.u);
  170. }
  171. }
  172. }
  173. }
  174. int count = ;
  175. memset(vis, , sizeof(vis));
  176. for(int i=;i<=n;i++)
  177. {
  178. cnt = ;
  179. if(!vis[i])
  180. {
  181. count++;
  182. vis[i] = ;
  183. solve(i);
  184. }
  185. }
  186. printf("%d\n", count);
  187. memset(vis, , sizeof(vis));
  188. for(int i=;i<=n;i++)
  189. {
  190. cnt = ;
  191. if (vis[i]) continue;
  192. vis[i] = ;
  193. solve(i);
  194.  
  195. printf("%d ", cnt);
  196. for (int j = ; j < cnt; j++) printf("%d ", out[j]);
  197. printf("%d\n", out[cnt]);
  198. }
  199. return ;
  200. }

网络流 I - Fox And Dinner CodeForces - 510E的更多相关文章

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

    大意: 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. codeforces 510E. Fox And Dinner 网络流

    题目链接 给出n个人, 以及每个人的值, 要求他们坐在一些桌子上面, 每个桌子如果有人坐, 就必须做3个人以上. 并且相邻的两个人的值加起来必须是素数.每个人的值都>=2. 由大于等于2这个条件 ...

  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 510E Fox And Dinner

    网络流. 原点到偶数连边,容量为2, 奇数到汇点连边,容量为2, 偶数到与之能凑成素数的奇数连边,容量为1 如果奇数个数不等于偶数个数,输出不可能 如果原点到偶数的边不满流,输出不可能 剩下的情况有解 ...

  7. Codeforces 510 E. Fox And Dinner

    题目链接:http://codeforces.com/problemset/problem/510/E 乍一看和那啥魔术球问题有点神似啊/XD 其实是不一样的. 解决这道问题的关键在于发现若是相邻的两 ...

  8. 【Codeforces】512C Fox and Dinner

    [解析]欧拉筛法,奇偶分析.建二分图,网络流 [Analysis] http://blog.csdn.net/qq574857122/article/details/43453087. 所谓的连通块就 ...

  9. CodeForces Round #290 Fox And Dinner

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

随机推荐

  1. openwrite使用说明

    访问官网https://openwrite.cn/注册登录 访问https://openwrite.cn/plugin-chrome/ 下载插件和安装插件"OpenWrite助手1.1.4& ...

  2. Scanner的小细节

    Scanner对象是用来接收键盘输入的数据的,可以接收字符串,数字,浮点数,大数等多种数据. Scanner scanner = new Scanner(System.in); System.out. ...

  3. 【Java】标识符 & 命名规则

    Java的标识符和命名规则 什么是标识符[Identifier]? 指用来标识某个实体的一个符号.在不同的应用环境下有不同的含义. 在编程语言中,标识符是开发者编程时使用的名字,对于变量.常量.函数. ...

  4. threejs使用各种坑实验过程

    第一次使用threejs到实际项目中,开始的时候心情有点小激动,毕竟是第一次嘛,然而做着做着就感受到这玩意水好深,满满的都是坑,填都填不过来.经过老板20天惨无人道的摧残,终于小有成就. 因为第一次搞 ...

  5. 作为python开发者,这几个PyCharm 技巧你必须掌握!

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行获取htt ...

  6. 如果这篇文章说不清epoll的本质,那就过来掐死我吧!

    转载自:https://www.toutiao.com/i6683264188661367309/ 目录 一.从网卡接收数据说起 二.如何知道接收了数据? 三.进程阻塞为什么不占用cpu资源? 四.内 ...

  7. 统计字符串中每种字符出现的评率(HashMap中getOrDefault(K, V)方法的使用)

    为了统计字符串中每种字符出现的频率,使用HashMap这种数据结构.其中,字符作为Key,出现的频率作为Value. 基本算法为: 1. 将字符串分成字符数组 2. (1)如果HashMap中的Key ...

  8. Java类的使用

    在一个Java文件中写两个类:一个基本的类,一个测试类.注意:文件名称和测试类名称一致. 如何使用呢?创建对象使用.如何创建对象呢?格式:类名 对象名 = new 类名(); Student s = ...

  9. tensorflow1.0 变量加法

    import tensorflow as tf state = tf.Variable(0,name='counter') print(state.name) one = tf.constant(1) ...

  10. TensorFlow-keras 100分类

    import os os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' from tensorflow.python.keras.datasets import cifa ...