网络流(最大流)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

43 4 8 9

Output

14 1 2 4 3

Input

52 2 2 2 2

Output

Impossible

Input

122 3 4 5 6 7 8 9 10 11 12 13

Output

112 1 2 3 6 5 12 9 8 7 10 11 4

Input

242 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

Output

36 1 2 3 6 5 410 7 8 9 12 15 14 13 16 11 108 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 }
时间: 2024-08-08 05:36:33

网络流(最大流)CodeForces 512C:Fox And Dinner的相关文章

Codeforces 512C Fox And Dinner 奇偶建图 网络流

题目链接:点击打开链接 题意: 给定n个人和其权值. 让人坐到任意多张圆形的桌子上使得任意两个相邻的人权值和为素数,且一张桌子至少3个人 输出桌子数和每张桌子坐的人(输出任意一个具体方案) 思路: 首先人的权值都是>=2的,也是就说组合成的素数一定是奇数 奇数 = 奇数+偶数.所以桌子上的人一定是奇偶交错的,而且一张桌子人数是偶数个(即n必须为偶数,一半是奇数,一半是偶数) 由上得:一个奇数要选择2个偶数,一个偶数要被2个奇数选择. 所以得到一个二部图,X集为奇数,Y集为偶数 网络流: 奇数连源

codeforces 510E. Fox And Dinner 网络流

题目链接 给出n个人, 以及每个人的值, 要求他们坐在一些桌子上面, 每个桌子如果有人坐, 就必须做3个人以上. 并且相邻的两个人的值加起来必须是素数.每个人的值都>=2. 由大于等于2这个条件, 可以知道素数都是奇数, 那么很明显就需要一奇一偶相邻这样做, 那么一个桌子上必定有偶数个人. 一个奇数旁边有两个偶数, 一个偶数旁边有两个奇数. 所以可以先判断n是否为偶数, 如果是奇数直接输出不可能. 然后开始奇偶建边, 源点和奇数建边, 权值为2, 因为一个奇数需要和两个偶数匹配: 偶数和汇点建边

CodeForces 510E Fox And Dinner

CodeForces 510E 素数打表+最大流+最大流打印路径 注意到ai (2 ≤ ai ≤ 104).那么题中的所有素数一定是一个奇数和一个偶数的和.那么所有的桌子都是偶环 将所有的偶数点连接超级源点,奇数点连接超级汇点,容量都为2.将所有的偶数点与奇数点间建容量为1的边,若满流,则可以满足条件 画个图可以知道这样建图是正确的→_→,怎么能想到这一点呢?弱不造 #include<cstdio> #include<cstring> #include<algorithm&g

CF510E. Fox And Dinner

CF510E. Fox And Dinner https://codeforces.com/contest/510 分析: 由于\(a_i>2\), 相邻两个数一定一奇一偶,按奇偶建立二分图. 环上每个点度数都为2,因此只需要找是否每个点都能匹配两个. 建图跑dinic即可. 代码: #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #include

POJ训练计划3422_Kaka&#39;s Matrix Travels(网络流/费用流)

解题报告 题目传送门 题意: 从n×n的矩阵的左上角走到右下角,每次只能向右和向下走,走到一个格子上加上格子的数,可以走k次.问最大的和是多少. 思路: 建图:每个格子掰成两个点,分别叫"出点","入点", 入点到出点间连一个容量1,费用为格子数的边,以及一个容量∞,费用0的边. 同时,一个格子的"出点"向它右.下的格子的"入点"连边,容量∞,费用0. 源点向(0,0)的入点连一个容量K的边,(N-1,N-1)的出点向汇点连一

POJ训练计划2516_Minimum Cost(网络流/费用流)

解题报告 题意: 有n个商店,m个提供商,k种商品</span> n*k的矩阵,表示每个商店需要每个商品的数目: m*k矩阵,表示每个提供商拥有每个商品的个数 然后对于每个物品k,都有n*m的矩阵 i行j列表示 从j提供商向i商店运送一个k商品的代价是多少 判断所有的仓库能否满足所有客户的需求,如果可以,求出最少的运输总费用 思路: 建图的题,不能直接把所有信息建成图,因为n和m跟k都有关系,如果那样子建图的话,就要把k种拆成m类,每个仓库连向该仓库的第k种,然后再和n连线,有费用, 不过这样

POJ 1459 Power Network(网络流 最大流 多起点,多汇点)

Power Network Time Limit: 2000MS   Memory Limit: 32768K Total Submissions: 22987   Accepted: 12039 Description A power network consists of nodes (power stations, consumers and dispatchers) connected by power transport lines. A node u may be supplied

POJ 1273 Drainage Ditches(网络流 最大流)

Drainage Ditches Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 55893   Accepted: 21449 Description Every time it rains on Farmer John's fields, a pond forms over Bessie's favorite clover patch. This means that the clover is covered by

hdu 4289 Control(网络流 最大流+拆点)(模板)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4289 Control Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1545    Accepted Submission(s): 677 Problem Description You, the head of Department o

POJ 2455 Secret Milking Machine(搜索-二分,网络流-最大流)

Secret Milking Machine Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9658   Accepted: 2859 Description Farmer John is constructing a new milking machine and wishes to keep it secret as long as possible. He has hidden in it deep within