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.
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).
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.
4 3 4 8 9
1 4 1 2 4 3
5 2 2 2 2 2
Impossible
12 2 3 4 5 6 7 8 9 10 11 12 13
1 12 1 2 3 6 5 12 9 8 7 10 11 4
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
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
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只fox,每只fox有对应的年龄,现在要求给n只fox分桌。每个桌至少三只fox,而且相邻坐着的fox的年龄和需要是素数。
问能够分出来多少桌,每桌多少fox,然后输出每桌fox的编号。
思路:
思路来源于网络:http://www.cnblogs.com/yohaha/p/5042116.html
1、好题,首先建立一个网络(建图方法确实很有趣)。
①首先分析,我们可以将n只fox分成二分图,将奇数分成一堆,偶数分成一堆,构成二分图。其中奇数+奇数==偶数,偶数一定不是素数(抛去2)(而且已经保证了fox的年龄大于等于2.所以这里不用担心两个数加一起等于2的情况)。其中偶数+偶数==偶数,同理,那么我们能够保证每个集合中没有相交的元素相加可以构成素数。
②那么我们建立一个源点,将源点连入各个偶数节点,设定权值为2,表示其可以有两个相邻的小伙伴。
③那么我们再建立一个汇点,将各个奇数节点连入汇点,设定权值为2,表示同理。
④那么如果左边偶数数加上右边某个奇数数能够构成一个素数,那么其建一条有向边,从偶数连入奇数,设定权值为1.
2、建立好网络之后,跑一遍最大流,如果满流,说明桌位是可分的。
3、如果桌位是可分的(满流),我们对应Dfs求解即可。
Ac代码:
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
struct node
{
int from;
int to;
int w;
int next;
}e[1515151];
vector<int >mp[2050];
int vis[2050];
int head[2050];
int cur[2050];
int divv[2050];
int lx[2050];
int ly[2050];
int a[205];
int Is_or[165550];//0表示素数
int n,cont,ss,tt,contx,conty;
void add(int from,int to,int w)
{
e[cont].from=from;
e[cont].to=to;
e[cont].w=w;
e[cont].next=head[from];
head[from]=cont++;
}
void init()
{
memset(Is_or,0,sizeof(Is_or));
for(int j=2;j<sqrt(165540);j++)
{
if(Is_or[j]==0)
for(int k=j+j;k<=165540;k+=j)
Is_or[k]=1;
}
}
void getmap()
{
cont=0;
ss=n+1;
tt=ss+1;
contx=0,conty=0;
memset(head,-1,sizeof(head));
for(int i=1;i<=n;i++)
{
if(a[i]%2==0)
{
add(ss,i,2);
add(i,ss,0);
lx[contx++]=i;
}
else
{
add(i,tt,2);
add(tt,i,0);
ly[conty++]=i;
}
}
for(int i=0;i<contx;i++)
{
for(int j=0;j<conty;j++)
{
if(Is_or[a[lx[i]]+a[ly[j]]]==0)
{
add(lx[i],ly[j],1);
add(ly[j],lx[i],0);
}
}
}
}
int makedivv()
{
queue<int >s;
s.push(ss);
memset(divv,0,sizeof(divv));
divv[ss]=1;
while(!s.empty())
{
int u=s.front();
if(u==tt)return 1;
s.pop();
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
int w=e[i].w;
if(w&&divv[v]==0)
{
divv[v]=divv[u]+1;
s.push(v);
}
}
}
return 0;
}
int Dfs(int u,int maxflow,int tt)
{
if(u==tt)return maxflow;
int ret=0;
for(int &i=cur[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
int w=e[i].w;
if(w&&divv[v]==divv[u]+1)
{
int f=Dfs(v,min(maxflow-ret,w),tt);
e[i].w-=f;
e[i^1].w+=f;
ret+=f;
if(ret==maxflow)return ret;
}
}
return ret;
}
int Dinic()
{
int ans=0;
while(makedivv()==1)
{
memcpy(cur,head,sizeof(head));
ans+=Dfs(ss,0x3f3f3f3f,tt);
}
return ans;
}
void Dfss(int u,int tot)
{
mp[tot].push_back(u);
vis[u]=1;
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(vis[v]==1)continue;
int w=e[i].w;
if(v!=ss&&v!=tt)
{
if(i%2==0&&w==0)
{
Dfss(v,tot);
}
if(i%2==1&&e[i^1].w==0)
{
Dfss(v,tot);
}
}
}
}
int main()
{
init();
while(~scanf("%d",&n))
{
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
mp[i].clear();
}
getmap();
int tmp=Dinic();
if(tmp==n)
{
int tot=0;
for(int i=1;i<=n;i++)
{
if(vis[i]==0)
{
Dfss(i,++tot);
}
}
printf("%d\n",tot);
for(int i=1;i<=tot;i++)
{
printf("%d",mp[i].size());
for(int j=0;j<mp[i].size();j++)
{
printf(" %d",mp[i][j]);
}
printf("\n");
}
}
else printf("Impossible\n");
}
}