codeforces 510E. Fox And Dinner 网络流
给出n个人, 以及每个人的值, 要求他们坐在一些桌子上面, 每个桌子如果有人坐, 就必须做3个人以上。 并且相邻的两个人的值加起来必须是素数。每个人的值都>=2.
由大于等于2这个条件, 可以知道素数都是奇数, 那么很明显就需要一奇一偶相邻这样做, 那么一个桌子上必定有偶数个人。 一个奇数旁边有两个偶数, 一个偶数旁边有两个奇数。
所以可以先判断n是否为偶数, 如果是奇数直接输出不可能。
然后开始奇偶建边, 源点和奇数建边, 权值为2, 因为一个奇数需要和两个偶数匹配; 偶数和汇点建边, 同理权值也为2。
然后, 如果一个奇数和一个偶数相加得到的数是素数, 那么奇数向偶数连一条边, 权值为1。
这样跑一遍网络流, 看结果是否等于n, 如果不相等, 说明不可能。如果可能, dfs一下就可以求出几个桌子, 每个桌子上面几个人了。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define pb(x) push_back(x) 4 #define ll long long 5 #define mk(x, y) make_pair(x, y) 6 #define lson l, m, rt<<1 7 #define mem(a) memset(a, 0, sizeof(a)) 8 #define rson m+1, r, rt<<1|1 9 #define mem1(a) memset(a, -1, sizeof(a)) 10 #define mem2(a) memset(a, 0x3f, sizeof(a)) 11 #define rep(i, a, n) for(int i = a; i<n; i++) 12 #define ull unsigned long long 13 typedef pair<int, int> pll; 14 const double PI = acos(-1.0); 15 const double eps = 1e-8; 16 const int mod = 1e9+7; 17 const int inf = 1061109567; 18 const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} }; 19 const int maxn = 2e5; 20 int prime[20005]; 21 int q[maxn*2], head[maxn*2], dis[maxn/10], s, t, a[205], num, vis[205]; 22 struct node 23 { 24 int to, nextt, c; 25 node(){} 26 node(int to, int nextt, int c):to(to), nextt(nextt), c(c){} 27 }e[maxn*2]; 28 void init() { 29 num = 0; 30 mem1(head); 31 } 32 void pre() { 33 for(int i = 2; i<=20000; i++) { 34 if(!prime[i]) 35 for(int j = i*i; j<=20000; j+=i) { 36 prime[j] = 1; 37 } 38 } 39 } 40 void add(int u, int v, int c) { 41 e[num] = node(v, head[u], c); head[u] = num++; 42 e[num] = node(u, head[v], 0); head[v] = num++; 43 } 44 int bfs() { 45 mem(dis); 46 dis[s] = 1; 47 int st = 0, ed = 0; 48 q[ed++] = s; 49 while(st<ed) { 50 int u = q[st++]; 51 for(int i = head[u]; ~i; i = e[i].nextt) { 52 int v = e[i].to; 53 if(!dis[v]&&e[i].c) { 54 dis[v] = dis[u]+1; 55 if(v == t) 56 return 1; 57 q[ed++] = v; 58 } 59 } 60 } 61 return 0; 62 } 63 int dfs(int u, int limit) { 64 if(u == t) { 65 return limit; 66 } 67 int cost = 0; 68 for(int i = head[u]; ~i; i = e[i].nextt) { 69 int v = e[i].to; 70 if(e[i].c&&dis[v] == dis[u]+1) { 71 int tmp = dfs(v, min(limit-cost, e[i].c)); 72 if(tmp>0) { 73 e[i].c -= tmp; 74 e[i^1].c += tmp; 75 cost += tmp; 76 if(cost == limit) 77 break; 78 } else { 79 dis[v] = -1; 80 } 81 } 82 } 83 return cost; 84 } 85 int dinic() { 86 int ans = 0; 87 while(bfs()) { 88 ans += dfs(s, inf); 89 } 90 return ans; 91 } 92 vector <int> ve[205]; 93 void dfs1(int u, int pos) { 94 ve[pos].pb(u); 95 vis[u] = 1; 96 for(int i = head[u]; ~i; i = e[i].nextt) { 97 int v = e[i].to; 98 if(vis[v]) 99 continue; 100 if(v == t|| v == s) 101 continue; 102 if(i%2==0&&!e[i].c) { 103 dfs1(v, pos); 104 } 105 if(i%2==1&&!e[i^1].c) 106 dfs1(v, pos); 107 } 108 } 109 int main() 110 { 111 int n; 112 cin>>n; 113 init(); 114 pre(); 115 for(int i = 0; i<n; i++) { 116 scanf("%d", &a[i]); 117 } 118 if(n&1) { 119 cout<<"Impossible"<<endl; 120 return 0; 121 } 122 s = n+1, t = n+2; 123 for(int i = 0; i<n; i++) { 124 if(a[i]&1) { 125 add(s, i, 2); 126 } else { 127 add(i, t, 2); 128 } 129 } 130 for(int i = 0; i<n; i++) { 131 for(int j = i+1; j<n; j++) { 132 if((a[i]&1) != (a[j]&1)) { 133 if(!prime[a[i]+a[j]]) { 134 if(a[i]&1) 135 add(i, j, 1); 136 else 137 add(j, i, 1); 138 } 139 } 140 } 141 } 142 int ans = dinic(); 143 if(ans != n) { 144 cout<<"Impossible"<<endl; 145 return 0; 146 } 147 int cnt = 0; 148 for(int i = 0; i<n; i++) { 149 if(!vis[i]) { 150 dfs1(i, cnt++); 151 } 152 } 153 cout<<cnt<<endl; 154 for(int i = 0; i<cnt; i++) { 155 cout<<ve[i].size()<<" "; 156 for(int j = 0; j<ve[i].size(); j++) { 157 cout<<ve[i][j]+1<<" "; 158 } 159 cout<<endl; 160 } 161 return 0; 162 }