Codeforces - 510E
有 N只狐妖,其中年龄加起来为质数的可以坐在一次
求一种方案,使所有人都坐成若干个环
注意到每个人的年龄都大于等于2
这意味着所有的质数都是奇数
相邻两个一个是奇数,一个是偶数
所以整张图是一个二分图
然后跑网络流
源点对奇数点连容量为 2的边
偶数点对汇点连容量为 2的边
中间奇数点对偶数点连容量为 1的边
表示每个点至多有两个邻居
最后检查一下是否满流就行
#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cctype>
#include <map>
#include <set>
#include <queue>
#include <bitset>
#include <string>
#include <complex>
using namespace std;
typedef pair<int,int> Pii;
typedef long long LL;
typedef unsigned long long ULL;
typedef double DBL;
typedef long double LDBL;
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) MST(a,0)
#define SQR(a) ((a)*(a))
#define PCUT puts("\n----------")
#define PRI(x) cout << #x << ":" << x << endl;
const int maxn=200+10, maxm=4e4+10, maxp=2e4+10;
struct Graph
{
int ndn, edn, last[maxn];
int u[maxm*2], v[maxm*2], c[maxm*2], nxt[maxm*2];
void init(int _n){ndn=_n; edn=0; MST(last,-1);}
void adde(int _u, int _v, int _c)
{
u[edn]=_u; v[edn]=_v; c[edn]=_c;
nxt[edn]=last[_u];
last[_u]=edn++;
}
};
struct Dinic
{
Graph *G;
int S, T, dist[maxn], cur[maxn];
int bfs();
int dfs(int,int);
int solve(Graph*, int, int);
};
int N, A[maxn];
bool sieve[maxp];
bool vis[maxn];
vector<int> to[maxn];
vector<vector<int>> ans;
Graph G;
Dinic D;
void gen(int);
void dfs(int,vector<int>&);
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
#endif
for(int i=2; i<maxp; i++) if(!sieve[i]) for(int j=i*i; j<maxp; j+=i)
sieve[j] = 1;
int S,T;
while(~scanf("%d", &N))
{
S=N+1, T=N+2;
G.init(N+2);
for(int i=1; i<=N; i++) scanf("%d", &A[i]);
int sum = 0;
for(int i=1; i<=N; i++)
{
if(A[i]&1) G.adde(S,i,2), G.adde(i,S,0);
else G.adde(i,T,2), G.adde(T,i,0), sum+=2;
}
int eno = G.edn;
for(int e0=G.last[S]; ~e0; e0=G.nxt[e0])
for(int e1=G.last[T]; ~e1; e1=G.nxt[e1])
{
int u=G.v[e0], v=G.v[e1];
if(!sieve[A[u]+A[v]])
{
G.adde(u,v,1);
G.adde(v,u,0);
}
}
vector<int> res;
if(D.solve(&G,S,T)!=sum) puts("Impossible");
else
{
CLR(vis);
ans.clear();
for(int i=1; i<=N; i++) to[i].clear();
for(int e=eno; e<G.edn; e+=2) if(!G.c[e])
{
to[G.u[e]].push_back(G.v[e]);
to[G.v[e]].push_back(G.u[e]);
}
for(int i=1; i<=N; i++) if(!vis[i])
{
res.clear();
dfs(i, res);
ans.push_back(res);
}
cout << ans.size() << "\n";
for(auto now:ans)
{
cout << now.size();
for(auto ct:now) cout << " " << ct;
puts("");
}
}
}
return 0;
}
void dfs(int u, vector<int> &ans)
{
vis[u] = 1;
ans.push_back(u);
for(auto v:to[u]) if(!vis[v])
{
dfs(v, ans);
return;
}
}
int Dinic::solve(Graph *g, int s, int t)
{
G=g; S=s; T=t;
int res = 0;
while(bfs())
{
for(int i=1; i<=G->ndn; i++) cur[i] = G->last[i];
res += dfs(S, 1e9);
}
return res;
}
int Dinic::bfs()
{
MST(dist,-1);
dist[S] = 0;
queue<int> que;
que.push(S);
while(que.size())
{
int u=que.front(); que.pop();
for(int e=G->last[u]; ~e; e=G->nxt[e])
{
int v=G->v[e];
if(dist[v]==-1 && G->c[e]>0)
{
dist[v] = dist[u]+1;
que.push(v);
}
}
}
return ~dist[T];
}
int Dinic::dfs(int u, int tmin)
{
if(u==T || tmin==0) return tmin;
int nflw=0, f;
for(int &e=cur[u]; ~e; e=G->nxt[e])
{
int v=G->v[e];
if(dist[u]+1==dist[v] && (f=dfs(v,min(tmin, G->c[e]))) > 0)
{
G->c[e] -= f;
G->c[e^1] += f;
nflw += f;
tmin -= f;
if(tmin==0) break;
}
}
return nflw;
}