且每张桌上相邻两个人的权值和为素数,输出其中一种方案。
思路:容易想到二分图匹配,但是控制不了每桌人数>=3。由于相加的和为素数,则必然是一奇一偶相加,那么分奇偶两边建图,源点-(2)-奇数-(1)-偶数-(2)-汇点跑最大流即可,输出路径dfs时用双端队列就行。
# include <bits/stdc++.h>
using namespace std;
const int maxn = 250000;
struct node{int v, next, w;}edge[maxn];
int Next[maxn], cnt=0, source, sink, dis[maxn], q[maxn];
int e[203], o[203], a[203], vis[203], cur;
list<int>g[203];
bool ok(int x)
{
for(int i=2; i<=sqrt(x); ++i)
if(x%i==0) return false;
return true;
}
void add(int u, int v, int w)
{
edge[cnt]={v,Next[u], w};
Next[u]=cnt++;
edge[cnt]={u,Next[v],0};
Next[v]=cnt++;
}
bool bfs()
{
memset(dis, -1, sizeof(dis));
dis[source]=0;
int l=0, r=0;
q[r++]=source;
while(l<r)
{
int u=q[l++];
for(int i=Next[u]; ~i; i=edge[i].next)
{
int v=edge[i].v, w=edge[i].w;
if(w>0 && dis[v]==-1)
{
dis[v] = dis[u]+1;
q[r++]=v;
}
}
}
return dis[sink]!=-1;
}
int dfs(int u, int pre)
{
if(u == sink) return pre;
int ans=0, f=0;
for(int i=Next[u]; ~i; i=edge[i].next)
{
int v=edge[i].v, w=edge[i].w;
if(dis[v]==dis[u]+1 && w>0 && (f=dfs(v, min(w, pre))))
{
edge[i].w -= f;
edge[i^1].w += f;
pre -= f;
ans += f;
if(!pre) break;
}
}
if(ans) return ans;
dis[u]=-1;
return 0;
}
void dfs2(int u, int bl, int flag)
{
vis[u] = 1;
if(flag) g[bl].push_front(u);
else g[bl].push_back(u);
for(int i=Next[u]; ~i; i=edge[i].next)
{
int v=edge[i].v, w=edge[i].w;
if(v==source || v==sink) continue;
if((i&1) && w==1 && !vis[v]) dfs2(v, bl, flag);
if(!(i&1) && w==0 && !vis[v]) dfs2(v, bl, (u==cur)?!flag:flag);
}
}
int main()
{
memset(Next, -1, sizeof(Next));
int n, max_flow=0, tot=0;
scanf("%d",&n);
source=0, sink=n+1;
for(int i=1; i<=n; ++i)
{
scanf("%d",&a[i]);
if(a[i]&1) o[++o[0]]=i,add(source, i, 2);
else e[++e[0]]=i, add(i, sink, 2);
}
if(o[0] != e[0]) return 0*puts("Impossible");
for(int i=1; i<=o[0]; ++i)
for(int j=1; j<=e[0]; ++j)
if(ok(a[o[i]]+a[e[j]])) add(o[i], e[j], 1);
while(bfs()) max_flow += dfs(source, 0x3f3f3f3f);
if(max_flow != n) return 0*puts("Impossible");
for(int i=1; i<=n; ++i)
{
if(vis[i]) continue;
cur = i;
dfs2(i, ++tot, 1);
}
printf("%d\n",tot);
for(int i=1; i<=tot; ++i, puts(""))
{
printf("%d ",g[i].size());
for(int j:g[i]) printf("%d ",j);
}
return 0;
}