素数打表+最大流+最大流打印路径
注意到ai (2 ≤ ai ≤ 104).那么题中的所有素数一定是一个奇数和一个偶数的和。那么所有的桌子都是偶环
将所有的偶数点连接超级源点,奇数点连接超级汇点,容量都为2.将所有的偶数点与奇数点间建容量为1的边,若满流,则可以满足条件
画个图可以知道这样建图是正确的→_→,怎么能想到这一点呢?弱不造
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> using namespace std; const int maxn=208; const int maxm=20008; const int INF=0x7f7f7f7f; int sb[maxn],sx[maxn]; bool pri[maxm]; void shit() { memset(pri,false,sizeof(pri)); pri[2]=true; int i,j,x; for(i=3;i<=20000;i++) { x=sqrt(i); for(j=2;j<=x;j++) if(i%j==0) break; if(j>x) pri[i]=true; } } struct fuck{ int u,v,cap,next; }edge[maxm]; int tol; int head[maxn]; void init() { tol=0; memset(head,-1,sizeof(head)); } void addedge(int u,int v,int w) { edge[tol].u=u; edge[tol].v=v; edge[tol].next=head[u]; edge[tol].cap=w; head[u]=tol++; edge[tol].v=u; edge[tol].u=v; edge[tol].cap=0; edge[tol].next=head[v]; head[v]=tol++; } bool vis[maxn]; int dep[maxn],gap[maxn]; void bfs(int sour,int sink) { queue<int> q; memset(vis,false,sizeof(vis)); memset(dep,-1,sizeof(dep)); memset(gap,0,sizeof(gap)); q.push(sink); dep[sink]=0;gap[0]=1;vis[sink]=true; int u,v,i; while(!q.empty()) { u=q.front();q.pop(); for(i=head[u];i!=-1;i=edge[i].next) { v=edge[i].v; if(!vis[v]&&edge[i].cap==0) { vis[v]=true; dep[v]=dep[u]+1; q.push(v); gap[dep[v]]++; } } } } int cur[maxn],S[maxm]; int last; int sap(int sour,int sink) { bfs(sour,sink); int max_flow=0,i,u; for(i=0;i<=last;i++) cur[i]=head[i]; int top=0; u=sour; while(dep[sour]<last) { if(u==sink) { int temp=INF,inser; for(i=0;i<top;i++) { if(edge[S[i]].cap<temp) { temp=edge[S[i]].cap; inser=i; } } for(i=0;i<top;i++) { edge[S[i]].cap-=temp; edge[S[i]^1].cap+=temp; } max_flow+=temp; top=inser; u=edge[S[top]].u; } if(u!=sink&&gap[dep[u]-1]==0) break; for(i=cur[u];i!=-1;i=edge[i].next) if(edge[i].cap>0&&dep[u]==dep[edge[i].v]+1) break; if(i!=-1) { cur[u]=i; S[top++]=i; u=edge[i].v; } else { int mi=last; for(i=head[u];i!=-1;i=edge[i].next) { if(edge[i].cap==0) continue; if(mi>dep[edge[i].v]) { mi=dep[edge[i].v]; cur[u]=i; } } --gap[dep[u]]; dep[u]=mi+1; ++gap[dep[u]]; if(u!=sour) u=edge[S[--top]].u; } } return max_flow; } int zhan[maxn]; int lin[maxn]; int sum; int li[maxn]; int dian[maxn]; int w[maxn]; void dfs(int u,int idx) { vis[u]=true; sum++; int i; if(u<=idx) { for(i=head[u];i!=-1;i=edge[i].next) if(edge[i].cap==0&&edge[i].v!=0&&!vis[edge[i].v]) { lin[u]=edge[i].v; dfs(edge[i].v,idx); } } else { for(i=head[u];i!=-1;i=edge[i].next) if(edge[i].cap>0&&edge[i].v!=last-1&&!vis[edge[i].v]) { lin[u]=edge[i].v; dfs(edge[i].v,idx); } } } int main() { int i,j,n,m,x; shit(); while(scanf("%d",&n)==1) { int idx,idb; idx=idb=0; init(); for(i=1;i<=n;i++) { scanf("%d",&x); if(x&1) { sb[++idb]=x; dian[idb]=i; } else { sx[++idx]=x; w[idx]=i; } } for(i=1;i<=idx;i++) for(j=1;j<=idb;j++) { if(pri[sx[i]+sb[j]]) addedge(i,j+idx,1); } int sour,sink; sour=0;sink=n+1; for(i=1;i<=idx;i++) addedge(sour,i,2); for(i=1;i<=idb;i++) addedge(i+idx,sink,2); last=n+2; int ans=sap(sour,sink); if(ans!=n) printf("Impossible\n"); else { ans=0; int id=0; memset(vis,false,sizeof(vis)); memset(lin,-1,sizeof(lin)); for(i=1;i<=idx;i++) { if(!vis[i]) { sum=0; dfs(i,idx); li[id]=i; zhan[id++]=sum; } } printf("%d\n",id); for(i=0;i<id;i++) { printf("%d",zhan[i]); int pa=li[i]; while(pa!=-1) { if(pa<=idx) printf(" %d",w[pa]); else printf(" %d",dian[pa-idx]); pa=lin[pa]; } printf("\n"); } } } return 0; }
时间: 2024-10-26 05:59:54