CF510E: Fox And Dinner
E. Fox And Dinner
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
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:
Each fox is sitting at some table.
Each table has at least 3 foxes sitting around it.
The sum of ages of any two adjacent foxes around each table should be a prime number.
If k foxes f1, f2, ..., 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
Copy
4
3 4 8 9
output
1
4 1 2 4 3
input
Copy
5
2 2 2 2 2
output
Impossible
input
Copy
12
2 3 4 5 6 7 8 9 10 11 12 13
output
1
12 1 2 3 6 5 12 9 8 7 10 11 4
input
Copy
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
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.
奇數偶數建邊跑一遍dinic,dfs跑一遍判斷哪個桌子
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1000;
const int inf = 0x3f3f3f3f;
int level[maxn], n, f, d;
list<int>g[100];
bool vis[300];
int num[300];
bool ok(int x)
{
for (int i = 2; i <= sqrt(x); ++i)
if (x%i == 0) return false;
return true;
}
struct node {
int to, cap, rev;
node(int _to, int _cap, int _rev) :to(_to), cap(_cap), rev(_rev) {}
};
vector<node>edge[maxn];
void add_node(int a, int b, int c) {
//printf("from %d to %d is %d\n", a, b, c);
edge[a].push_back(node(b, c, edge[b].size()));
edge[b].push_back(node(a, 0, edge[a].size() - 1));
}
int bfs(int s, int t) {
memset(level, -1, sizeof(level));
queue<int>q;
q.push(s);
level[s] = 0;
while (!q.empty()) {
int tmp = q.front(); q.pop();
for (int i = 0; i < edge[tmp].size(); i++) {
node &tmp1 = edge[tmp][i];
if (level[tmp1.to] == -1 && tmp1.cap > 0) {
level[tmp1.to] = level[tmp] + 1;
q.push(tmp1.to);
}
}
}
return level[t] != -1;
}
int dfs(int s, int t, int flow) {
if (s == t) return flow;
int ans = 0;
for (int i = 0; i < edge[s].size(); i++) {
node &tmp = edge[s][i];
if (flow > ans&&tmp.cap > 0 && level[tmp.to] == level[s] + 1) {
int d = dfs(tmp.to, t, min(tmp.cap, flow - ans));
if (d > 0) {
tmp.cap -= d;
edge[tmp.to][tmp.rev].cap += d;
ans += d;
}
}
}
if (ans == 0)
level[s] = -1;
return ans;
}
int dinic(int s, int t) {
int ans = 0, tf;
while (bfs(s, t))
while (tf = dfs(s, t, inf))
ans += tf;
return ans;
}
int t, s,a[300];
void dfs1(int u, int k) {
if (vis[u])return;
g[k].push_back(num[u]);
vis[u] = 1;
for (node i : edge[u]) {
if (i.to == t || i.to == s)continue;
if (a[num[u]] & 1 && i.cap == 0 && !vis[i.to]) {//網路流跑完之後,邊的值會變為0,反向邊的值會變為以前正向邊的值
dfs1(i.to, k);
}
else if (!(a[num[u]] & 1) && i.cap == 1 && !vis[i.to]) {
dfs1(i.to, k);
}
}
}
int main()
{
int b, c;
scanf("%d", &n);
t=n+2;//終點
s=n+1;//起點
vector<int>jp[2];
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
jp[a[i] & 1].push_back(a[i]);
if (a[i] & 1)num[jp[1].size() - 1] = i;//判斷在jp陣列中的數字在a陣列的相對位置
else num[jp[0].size() - 1 + n / 2] = i;//
}
if (jp[0].size()!=jp[1].size()) {//如果不對稱,則不可能
printf("Impossible\n");
return 0;
}
int cnt = 0;
for (int i = 0; i < jp[1].size(); i++) {
//cout << jp[1][i] <<' '<<num[i]<< endl;
for (int j = 0; j < jp[0].size(); j++) {
if (ok(jp[1][i] + jp[0][j]))add_node(i, j + n/2, 1);
}
}
for (int i = 0; i < jp[0].size(); i++) {
add_node(s, i, 2);
add_node(i + n / 2, t, 2);
}
if (dinic(s, t) == n) {
cnt = 0;
for (int i = 0; i < n; i++) {
if (vis[i])continue;
dfs1(i, cnt++);
}
cout << cnt << endl;
for (int i = 0; i < cnt; i++) {
printf("%d ", g[i].size());
for (int j : g[i]) printf("%d ", j);
cout << endl;
}
}else printf("Impossible\n");
return 0;
}