-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathno prime sum.cpp
138 lines (127 loc) · 3.02 KB
/
no prime sum.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include <bits/stdc++.h>
using namespace std;
const int mx = 3123;
const int ms = 3e3; // Quantidade maxima de vertices
const int me = 1e6; // Quantidade maxima de arestas
int adj[ms], to[me], ant[me], wt[me], z, n;
int copy_adj[ms], fila[ms], level[ms];
void clear() { // Lembrar de chamar no main
memset(adj, -1, sizeof adj);
z = 0;
}
void add(int u, int v, int k) {
to[z] = v;
ant[z] = adj[u];
wt[z] = k;
adj[u] = z++;
swap(u, v);
to[z] = v;
ant[z] = adj[u];
wt[z] = 0; // Lembrar de colocar = 0
adj[u] = z++;
}
int bfs(int source, int sink) {
memset(level, -1, sizeof level);
level[source] = 0;
int front = 0, size = 0, v;
fila[size++] = source;
while(front < size) {
v = fila[front++];
for(int i = adj[v]; i != -1; i = ant[i]) {
if(wt[i] && level[to[i]] == -1) {
level[to[i]] = level[v] + 1;
fila[size++] = to[i];
}
}
}
return level[sink] != -1;
}
int dfs(int v, int sink, int flow) {
if(v == sink) return flow;
int f;
for(int &i = copy_adj[v]; i != -1; i = ant[i]) {
if(wt[i] && level[to[i]] == level[v] + 1 &&
(f = dfs(to[i], sink, min(flow, wt[i])))) {
wt[i] -= f;
wt[i ^ 1] += f;
return f;
}
}
return 0;
}
const int SOURCE = 2001, SINK = 2002;
int maxflow(int source, int sink) {
int ret = 0, flow;
while(bfs(source, sink)) {
memcpy(copy_adj, adj, sizeof adj);
while((flow = dfs(source, sink, 1 << 30))) {
ret += flow;
}
}
return ret;
}
vector<int> coverU, U, coverV, V; // ITA - Partição U LEFT, partição V RIGHT, 1 indexed
bool Zu[mx], Zv[mx];
int pairU[mx], pairV[mx];
void getreach(int u) {
if (u == 0 || Zu[u]) return;
Zu[u] = true;
for (int i = adj[u]; ~i; i = ant[i]) {
int v = to[i];
if (v == SOURCE || v == pairU[u]) continue;
Zv[v] = true;
getreach(pairV[v]);
}
}
void minimumcover () {
for (auto i : U) {
for (int j = adj[i]; ~j; j = ant[j]) {
if (!(j&1) && !wt[j]) {
pairU[i] = to[j], pairV[to[j]] = i;
}
}
}
memset(&Zu, 0, sizeof Zu);
memset(&Zv, 0, sizeof Zv);
for (auto u : U) {
if (pairU[u] == 0) getreach(u);
}
coverU.clear(), coverV.clear();
for (auto u : U) {
if (!Zu[u]) coverU.push_back(u);
}
for (auto v : V) {
if (Zv[v]) coverV.push_back(v);
}
}
bool isp[212345];
int main () {
memset(isp, 1, sizeof isp);
for (int i = 2; i < 212345; i++) {
if(!isp[i]) continue;
for (int j = 2*i; j < 212345; j += i) isp[j] = 0;
}
int n;
cin >> n;
int v[n+1];
clear();
for (int i = 1; i <= n; i++) {
cin >> v[i];
for (int j = 1; j < i; j++) {
if (isp[v[i] + v[j]]) {
if (v[i]&1) add(i, j, 1);
else add(j, i, 1);
}
}
if (v[i]&1) add(SOURCE, i, 1), U.push_back(i);
else add(i, SINK, 1), V.push_back(i);
}
cout << maxflow(SOURCE, SINK) << endl;
minimumcover();
vector<int> ans;
for (auto u: coverU) ans.push_back(u);
for (auto u: coverV) ans.push_back(u);
for (int i = 0; i < ans.size(); i++) {
cout << v[ans[i]] << " \n"[i+1 == ans.size()];
}
}