CF 510E(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:

  1. Each fox is sitting at some table.
  2. Each table has at least 3 foxes sitting around it.
  3. The sum of ages of any two adjacent foxes around each table should be a prime number.

If k foxes f1f2, ..., fk are sitting around table in clockwise order, then for 1 ≤ i ≤ k - 1fi 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.

Sample test(s)
input
4
3 4 8 9
output
1
4 1 2 4 3
input
5
2 2 2 2 2
output
Impossible
input
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
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.


由于事先规定ai>=2,所以a+b>=4 

如果a+b是素数,那它是奇数=奇数+偶数

原题的环就变成 ji,ou,ji,ou。。。这样的 ,所以年龄中,奇数个数=偶数个数

把奇数,偶数换在2边,做2分图,a+b是素数就连边。

原题转变成一个2分图匹配,每个点要匹配2条边

故:建s,t,s向每个偶数连容量为2的边,同理,奇数向t连

建图,网络流



#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<iostream>
#include<cmath>
#include<cctype>
#include<ctime>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=next[p])  
#define Lson (x<<1)
#define Rson ((x<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define MAXN (400+10)
#define MAXM ((200+100*100)*2+100000)
#define MAXAi (10000+10)
long long mul(long long a,long long b){return (a*b)%F;}
long long add(long long a,long long b){return (a+b)%F;}
long long sub(long long a,long long b){return (a-b+(a-b)/F*F+F)%F;}
typedef long long ll;
int n,a[MAXN],a1[MAXN],a2[MAXN],num1[MAXN],num2[MAXN];
class Max_flow  //dinic+当前弧优化     
{      
public:      
    int n,s,t;      
    int q[MAXN];      
    int edge[MAXM],next[MAXM],pre[MAXN],weight[MAXM],size;      
    void addedge(int u,int v,int w)        
    {        
        edge[++size]=v;        
        weight[size]=w;        
        next[size]=pre[u];        
        pre[u]=size;        
    }        
    void addedge2(int u,int v,int w){addedge(u,v,w),addedge(v,u,0);}       
    bool b[MAXN];      
    int d[MAXN];      
    bool SPFA(int s,int t)        
    {        
        For(i,n) d[i]=INF;      
        MEM(b)      
        d[q[1]=s]=0;b[s]=1;        
        int head=1,tail=1;        
        while (head<=tail)        
        {        
            int now=q[head++];        
            Forp(now)        
            {        
                int &v=edge[p];        
                if (weight[p]&&!b[v])        
                {        
                    d[v]=d[now]+1;        
                    b[v]=1,q[++tail]=v;        
                }        
            }            
        }        
        return b[t];        
    }       
    int iter[MAXN];    
    int dfs(int x,int f)    
    {    
        if (x==t) return f;    
        Forpiter(x)    
        {    
            int v=edge[p];    
            if (weight[p]&&d[x]<d[v])    
            {    
                  int nowflow=dfs(v,min(weight[p],f));    
                  if (nowflow)    
                  {    
                    weight[p]-=nowflow;    
                    weight[p^1]+=nowflow;    
                    return nowflow;    
                  }    
            }    
        }    
        return 0;    
    }    
    int max_flow(int s,int t)    
    {    
        int flow=0;    
        while(SPFA(s,t))    
        {    
            For(i,n) iter[i]=pre[i];    
            int f;    
            while (f=dfs(s,INF))    
                flow+=f;     
        }    
        return flow;    
    }     
    void mem(int n,int s,int t)      
    {      
        (*this).n=n;    
        (*this).t=t;      
        (*this).s=s;      
            
        size=1;      
        MEM(pre)     
    }      
}S;      

int p[MAXAi*2]={0},size=0;
bool b[MAXAi*2]={0};
const int N=20000;
void make_prime()
{
	MEM(b)
	Fork(i,2,N)
	{
		if (!b[i]) p[++size]=i;
		For(j,size)
		{
			if (p[j]*i>N) break;  
			b[p[j]*i]=1;
			if (i%p[j]==0) break;
		}
	}	
}
int ans[MAXN][3],st[MAXN][MAXN]={0};
int main()
{
//	freopen("CF510E.in","r",stdin);
//	freopen(".out","w",stdout);
	
	make_prime();
	cin>>n;
	
	int n1=0,n2=0;
	For(i,n)
	{	
		scanf("%d",&a[i]);
		if (a[i]&1) a1[++n1]=a[i],num1[n1]=i;
		else a2[++n2]=a[i],num2[n2]=i; 
	}
	
	if (n1^n2)
	{
		cout<<"Impossible"<<endl;
		return 0;
	}
	else
	{
		const int s=1,t=n+2;
		S.mem(t,s,t);
		For(i,n1) S.addedge2(s,i+1,2);
		For(i,n2) S.addedge2(1+n1+i,t,2);
		
		For(i,n1)
			For(j,n2)
				if (!b[a1[i]+a2[j]])
					S.addedge2(i+1,1+n1+j,1);
		if (S.max_flow(s,t)^n) 
		{
			cout<<"Impossible"<<endl;
			return 0;
		}
		else
		{
			int tot=0; 
			For(i,n1)
			{
				for(int p=S.pre[i+1];p;p=S.next[p])
				{
					if (S.weight[p]==0) ans[++tot][1]=num1[i],ans[tot][2]=num2[S.edge[p]-1-n1]; 
				}
			}
			MEM(b)
			
		//	For(i,tot) cout<<ans[i][1]<<' '<<ans[i][2]<<endl;
			
			int m=0;
			For(i,tot)
				if (!b[i])
				{
					b[i]=1;
					st[++m][1]=ans[i][1],st[m][2]=ans[i][2];
					int st_size=2;
					
					while (st[m][1]^st[m][st_size])
					{
						For(i,tot)
							if (!b[i])
							{
								if (ans[i][1]==st[m][st_size]) {st[m][++st_size]=ans[i][2];b[i]=1; break;}
								if (ans[i][2]==st[m][st_size]) {st[m][++st_size]=ans[i][1];b[i]=1; break;}
							} 
					}
					st[m][0]=st_size-1;										 
				}
			cout<<m<<endl;
			For(i,m)
			{
				cout<<st[i][0];
				For(j,st[i][0]) printf(" %d",st[i][j]);
				putchar('\n');
			}		
		}
		
		
		
	} 
	
	return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值