题目链接:http://codeforces.com/problemset/problem/510/E
乍一看和那啥魔术球问题有点神似啊/XD
其实是不一样的。
解决这道问题的关键在于发现若是相邻的两个数的和是质数,那么他们必定是一奇一偶!
而且一个奇数旁边一定是两个偶数,一个偶数旁边一定是两个奇数(因为是一个大于$3$的环)
秒啊!这就变成了匹配模型。
源点向所有值为奇数的点连容量为$2$边,值为奇数的点向所有与它的和为质数的且值为偶数点连容量为$1$边,所有值为偶数的点向汇点连容量为$2$的边。
跑一边最大流,我们是不是就求出了最大的合法的匹配方案?
如果最大流为$n$才说明了每一个点都匹配上了。
考虑输出方案,$DFS$在$Dinic$之后留下的图,如果流量发生了变化则沿这条路径走下去(当然不能走到源点或者汇点)
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<vector> 5 #include<cstdlib> 6 #include<cmath> 7 #include<cstring> 8 using namespace std; 9 #define maxn 1010 10 #define inf 0x7fffffff 11 #define llg int 12 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); 13 llg n,m,ans,c[maxn],cnt1,cnt2,tot[maxn]; 14 llg d[maxn][maxn]; 15 inline int getint() 16 { 17 int w=0,q=0; char c=getchar(); 18 while((c<'0' || c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); 19 while (c>='0' && c<='9') w=w*10+c-'0', c=getchar(); return q ? -w : w; 20 } 21 22 struct DINIC 23 { 24 llg N; 25 vector<llg>a[maxn],ba[maxn],val[maxn],stval[maxn]; 26 llg dl[maxn],deep[maxn]; 27 bool bj[maxn]; 28 29 void link(llg x,llg y,llg z) 30 { 31 a[x].push_back(y),val[x].push_back(z); stval[x].push_back(z); 32 a[y].push_back(x),val[y].push_back(0); stval[y].push_back(0); 33 ba[x].push_back(a[y].size()-1),ba[y].push_back(a[x].size()-1); 34 } 35 36 llg dfs(llg x,llg low) 37 { 38 llg va=0,inc=0; 39 if (x==N) return low; 40 llg w=a[x].size(),v; 41 for (llg i=0;i<w;i++) 42 { 43 v=a[x][i]; 44 if (deep[x]+1==deep[v] && val[x][i]>0 && (va=dfs(v,min(low,val[x][i])))) 45 { 46 val[x][i]-=va; val[v][ba[x][i]]+=va; inc+=va; 47 return va; 48 } 49 } 50 if (!inc) deep[x]=-1; 51 return 0; 52 } 53 54 void fencen() 55 { 56 llg x,w,v; deep[0]=0; 57 memset(bj,0,sizeof(bj)); 58 llg head=0,tail=1; dl[1]=0; bj[0]=1; 59 do 60 { 61 x=dl[++head]; w=a[x].size(); 62 for (llg i=0;i<w;i++) 63 { 64 v=a[x][i]; 65 if (bj[v] || val[x][i]<=0) continue; 66 dl[++tail]=v; 67 deep[v]=deep[x]+1; bj[v]=1; 68 } 69 }while (head!=tail); 70 } 71 72 llg dinic() 73 { 74 llg ans=0; 75 while (1) 76 { 77 fencen(); 78 if (!bj[N]) break; 79 ans+=dfs(0,inf); 80 } 81 return ans; 82 } 83 84 void DFS(llg x) 85 { 86 bj[x]=1; 87 tot[ans]++; 88 d[ans][tot[ans]]=x; 89 llg w=a[x].size(),v; 90 for (llg i=0;i<w;i++) 91 { 92 v=a[x][i]; 93 if (v==0 || v==N || bj[v]) continue; 94 if (stval[x][i]==val[x][i]) continue; 95 DFS(v); 96 } 97 } 98 99 bool pd(llg x) 100 { 101 llg cs=0,w=a[x].size(),v; 102 for (llg i=0;i<w;i++) 103 { 104 v=a[x][i]; 105 if (v==0 || v==N) continue; 106 if (bj[v] || val[x][i]==stval[x][i]) continue; 107 cs++; 108 } 109 if (cs>2) return 0;else return 1; 110 } 111 112 void make_ans() 113 { 114 memset(bj,0,sizeof(bj)); 115 while (1) 116 { 117 bool WK=0; 118 for (llg i=1;i<=n;i++) 119 if (!bj[i]) 120 { 121 if (!pd(i)) continue; 122 WK=1; 123 ans++; 124 DFS(i); 125 } 126 if (!WK) break; 127 } 128 } 129 }G; 130 131 bool check(llg v1,llg v2) 132 { 133 llg x=v1+v2; 134 llg up=sqrt(x+1); 135 for (llg i=2;i<=up;i++) 136 if (x%i==0) return 0; 137 return 1; 138 } 139 140 void init() 141 { 142 cin>>n; 143 for (llg i=1;i<=n;i++) c[i]=getint(); 144 for (llg i=1;i<=n;i++) 145 { 146 if (c[i]%2) G.link(0,i,2),cnt1++; else G.link(i,n+1,2),cnt2++; 147 if (c[i]%2==0) continue; 148 for (llg j=1;j<=n;j++) 149 if (i!=j && check(c[i],c[j])) 150 G.link(i,j,1); 151 } 152 G.N=n+1; 153 } 154 155 int main() 156 { 157 yyj("flows"); 158 init(); 159 if (cnt1!=cnt2) {cout<<"Impossible"; return 0;} 160 llg flows=G.dinic(); 161 if (flows!=n) {cout<<"Impossible"; return 0;} 162 G.make_ans(); 163 cout<<ans<<endl; 164 for (llg i=1;i<=ans;i++) 165 { 166 cout<<tot[i]<<" "; 167 for (llg j=1;j<=tot[i];j++) cout<<d[i][j]<<" "; 168 cout<<endl; 169 } 170 return 0; 171 }