网络流(最大流)CodeForces 512C:Fox And Dinner

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 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.

 

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 Input

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
  建二分图,再用流量为2限制度数,即可用网络流AC。
  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <queue>
  5 using namespace std;
  6 const int N=210,M=60010,INF=1000000000;
  7 int cnt,fir[N],fron[N],nxt[M],to[M],cap[M];
  8 int dis[N],gap[N],path[N],vis[N],q[N],h,t;
  9 int n,m,a[N],tp[N],tot;vector<int>ans[N];
 10 struct Net_Flow{
 11     void Init(){
 12         memset(fir,0,sizeof(fir));
 13         memset(gap,0,sizeof(gap));
 14         memset(dis,0,sizeof(dis));
 15         h=t=cnt=1;
 16     }
 17     void addedge(int a,int b,int c){
 18         nxt[++cnt]=fir[a];to[fir[a]=cnt]=b;cap[cnt]=c;
 19         nxt[++cnt]=fir[b];to[fir[b]=cnt]=a;cap[cnt]=0;
 20     }
 21     bool BFS(int S,int T){
 22         dis[q[h]=T]=1;
 23         while(h<=t){
 24             int x=q[h++];
 25             for(int i=fir[x];i;i=nxt[i])
 26                 if(!dis[to[i]])dis[q[++t]=to[i]]=dis[x]+1;
 27         }
 28         return dis[S];
 29     }
 30     int ISAP(int S,int T){
 31         if(!BFS(S,T))return 0;
 32         for(int i=S;i<=T;i++)gap[dis[i]]+=1;
 33         for(int i=S;i<=T;i++)fron[i]=fir[i];
 34         int ret=0,f,p=S,Min;
 35         while(dis[S]<=T+1){
 36             if(p==T){f=INF;
 37                 while(p!=S){
 38                     f=min(f,cap[path[p]]);
 39                     p=to[path[p]^1];
 40                 }ret+=f,p=T;
 41                 while(p!=S){
 42                     cap[path[p]]-=f;
 43                     cap[path[p]^1]+=f;
 44                     p=to[path[p]^1];
 45                 }
 46             }
 47             for(int &i=fron[p];i;i=nxt[i])
 48                 if(cap[i]&&dis[to[i]]==dis[p]-1){
 49                     path[p=to[i]]=i;break;
 50                 }
 51             if(!fron[p]){
 52                 if(!--gap[dis[p]])break;Min=T+1;
 53                 for(int i=fir[p];i;i=nxt[i])
 54                     if(cap[i])Min=min(Min,dis[to[i]]);
 55                 gap[dis[p]=Min+1]+=1;fron[p]=fir[p];
 56                 if(p!=S)p=to[path[p]^1];    
 57             }    
 58         }    
 59         return ret;
 60     }
 61     void DFS(int x,int id){
 62         vis[x]=1;ans[id].push_back(x);
 63         for(int i=fir[x];i;i=nxt[i]){
 64             if(vis[to[i]]||to[i]<1||to[i]>n)continue;
 65             if(a[to[i]]%2==0&&cap[i^1]==0)DFS(to[i],id);
 66             if(a[to[i]]%2!=0&&cap[i]==0)DFS(to[i],id);
 67         }
 68     }
 69     void Solve(int S,int T){
 70         for(int x=1;x<=n;x++)
 71             if(a[x]%2==0&&!vis[x])
 72                 DFS(x,++tot);
 73         printf("%d\n",tot);
 74         for(int i=1;i<=tot;i++){
 75             printf("%d ",ans[i].size());
 76             for(int j=0;j<ans[i].size();j++)
 77                 printf("%d ",ans[i][j]);
 78             puts("");    
 79         }
 80     }
 81 }isap;
 82 int S,T;
 83 bool Check(int x){
 84     for(int i=2;i*i<=x;i++)
 85         if(x%i==0)return false;
 86     return true;    
 87 }
 88 int main(){
 89     scanf("%d",&n);isap.Init();T=n+1;
 90     if(n%2==1){puts("Impossible");return 0;}
 91     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
 92     for(int i=1;i<=n;i++){
 93         if(a[i]%2==0)isap.addedge(S,i,2);
 94         else isap.addedge(i,T,2);
 95     }    
 96     for(int i=1;i<=n;i++)if(a[i]%2==0)
 97         for(int j=1;j<=n;j++)if(a[j]%2)
 98             if(Check(a[i]+a[j]))
 99                 isap.addedge(i,j,1);
100     if(isap.ISAP(S,T)!=n){
101         puts("Impossible");
102         return 0;
103     }            
104     isap.Solve(S,T);
105     return 0;
106 }

 

转载于:https://www.cnblogs.com/TenderRun/p/5928235.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值