Fox And Dinner - CodeForces 510 E dinic 网络流 奇偶匹配

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

题意:给你n个值,让你将这n个值围成任意圈,使得每个圈中个数都大于三个并且每个数与它相邻的数的和为素数。

思路:如果和为素数的话,那么必是一个奇数加上一个偶数。所以让0到奇数的f=2,偶数到n+1的f=2,如果奇偶的和为素数时让他们的f=1。

AC代码如下:

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
struct node
{
    int v,flow,next;
}edge[40010];
int n,Prime[20010],num[210],Head[210],d[210],e,desk[210][210],vis[210],INF=1e9,link[210][210];
queue<int> qu;
void add(int u,int v,int f)
{
    edge[e].v=v;
    edge[e].flow=f;
    edge[e].next=Head[u];
    Head[u]=e;
    e++;
}
void init()
{
    int i,j,k;
    e=0;
    memset(Head,-1,sizeof(Head));
    for(i=1;i<=n;i++)
       if(num[i]&1)
       {
           add(0,i,2);
           add(i,0,2);
       }
       else
       {
           add(i,n+1,2);
           add(n+1,i,0);
       }
    for(i=1;i<=n;i++)
       for(j=i+1;j<=n;j++)
       if(Prime[num[i]+num[j]]==0)
       {
           if(num[i]&1)
           {
               add(i,j,1);
               add(j,i,0);
           }
           else
           {
               add(j,i,1);
               add(i,j,0);
           }

       }
}
int bfs()
{
    int i,j,u,v;
    memset(d,-1,sizeof(d));
    while(!qu.empty())
      qu.pop();
    d[0]=0;
    qu.push(0);
    while(!qu.empty())
    {
        u=qu.front();
        qu.pop();
        for(j=Head[u];j!=-1;j=edge[j].next)
           if(edge[j].flow>0 && d[edge[j].v]==-1)
           {
               d[edge[j].v]=d[u]+1;
               if(edge[j].v==n+1)
                 return 1;
               qu.push(edge[j].v);
           }
    }
    return 0;
}
int dfs(int u,int f)
{
    if(u==n+1 || f==0)
      return f;
    int ans=0,v,i,j,k;
    for(j=Head[u];j!=-1;j=edge[j].next)
       if(edge[j].flow>0 && d[edge[j].v]==d[u]+1)
       {
           k=dfs(edge[j].v,min(edge[j].flow,f));
           edge[j].flow-=k;
           edge[j^1].flow+=k;
           ans+=k;
           f-=k;
           if(f==0)
             break;
       }
    d[u]=-1;
    return ans;
}
int dinic()
{
    int ans=0;
    while(bfs())
      ans+=dfs(0,INF);
    return ans;
}
void dfs2(int p,int u)
{
    int i,j,k;
    for(i=1;i<=n;i++)
      if(vis[i]==0 && link[u][i]==1)
       {
           vis[i]=1;
           desk[p][0]++;
           desk[p][desk[p][0]]=i;
           dfs2(p,i);
       }
}
int main()
{
    int i,j,k,ans,p;
    for(i=2;i<=200;i++)
       if(Prime[i]==0)
         for(j=i*2;j<=20000;j+=i)
            Prime[j]=1;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
       scanf("%d",&num[i]);
    init();
    ans=dinic();
    if(ans!=n)
      printf("Impossible\n");
    else
    {
        for(i=1;i<=n;i++)
           if(num[i]&1)
           for(j=Head[i];j!=-1;j=edge[j].next)
              if(edge[j].flow==0)
              {
                  link[i][edge[j].v]=1;
                  link[edge[j].v][i]=1;
              }
        p=0;
        for(i=1;i<=n;i++)
           if(vis[i]==0)
           {
               vis[i]=1;
               p++;
               desk[p][0]=1;
               desk[p][1]=i;
               dfs2(p,i);
           }
        printf("%d\n",p);
        for(i=1;i<=p;i++)
        {
            printf("%d",desk[i][0]);
            for(j=1;j<=desk[i][0];j++)
               printf(" %d",desk[i][j]);
            printf("\n");
        }
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值