Team them up!
https://odzkskevi.qnssl.com/9698e76abf2d161889085123803f9464?v=1508663873
【题解】
把“两个人不相互认识”连边,形成若干连通分量
不难发现每个联通分量进行黑白染色后,必定选黑或选白
DP[i][j]表示前i个连通块,选j个黑块是否可行
从dp[n][mid]开始向左右检查即可
因为边数开小以及偶数n的处理不当RE/WA了很多发
要用大数据测/对拍/手出数据验证程序的每一部分
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <vector> 6 #define min(a, b) ((a) < (b) ? (a) : (b)) 7 #define max(a, b) ((a) > (b) ? (a) : (b)) 8 9 inline void swap(int &a, int &b) 10 { 11 int tmp = a;a = b;b = tmp; 12 } 13 14 inline void read(int &x) 15 { 16 x = 0;char ch = getchar(), c = ch; 17 while(ch < '0' || ch > '9')c = ch, ch = getchar(); 18 while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar(); 19 if(c == '-')x = -x; 20 } 21 22 const int INF = 0x3f3f3f3f; 23 const int MAXN = 100 + 10; 24 25 struct Edge 26 { 27 int u,v,nxt; 28 Edge(int _u, int _v, int _nxt){u = _u;v = _v;nxt = _nxt;} 29 Edge(){} 30 }edge[MAXN * MAXN << 1]; 31 int head[MAXN], cnt; 32 inline void insert(int a, int b) 33 { 34 edge[++cnt] = Edge(a,b,head[a]); 35 head[a] = cnt; 36 } 37 38 int t,n,tot,x[MAXN],y[MAXN],b[MAXN],g[MAXN][MAXN],tag,dp[MAXN][MAXN],zhuanyi1[MAXN][MAXN], zhuanyi2[MAXN][MAXN], zhuanyi3[MAXN][MAXN]; 39 std::vector<int> xx[MAXN], yy[MAXN]; 40 41 int dfs(int u, int flag) 42 { 43 b[u] = flag; 44 if(flag == 1) ++ x[tot], flag = 2, xx[tot].push_back(u); 45 else flag = 1, ++ y[tot], yy[tot].push_back(u); 46 for(register int pos = head[u];pos;pos = edge[pos].nxt) 47 { 48 int v = edge[pos].v; 49 if(!b[v]) 50 { 51 if(dfs(v, flag)) 52 return 1; 53 } 54 else if(b[v] != flag) 55 return 1; 56 } 57 return 0; 58 } 59 60 void dfs2(int p, int q) 61 { 62 if(p == 0) return; 63 b[p] = zhuanyi3[p][q]; 64 dfs2(zhuanyi1[p][q], zhuanyi2[p][q]); 65 } 66 67 int check(int num) 68 { 69 if(!dp[tot][num]) return 0; 70 printf("%d ", num); 71 memset(b, 0, sizeof(b)); 72 dfs2(tot, num); 73 for(register int i = 1;i <= tot;++i) 74 if(b[i] == 1) 75 for(register int j = 0;j < xx[i].size();++ j) 76 printf("%d ", xx[i][j]); 77 else 78 for(register int j = 0;j < yy[i].size();++ j) 79 printf("%d ", yy[i][j]); 80 printf(" %d ", n - num); 81 for(register int i = 1;i <= tot;++i) 82 if(b[i] == 1) 83 for(register int j = 0;j < yy[i].size();++ j) 84 printf("%d ", yy[i][j]); 85 else 86 for(register int j = 0;j < xx[i].size();++ j) 87 printf("%d ", xx[i][j]); 88 putchar(' '); 89 return 1; 90 } 91 92 void init() 93 { 94 tot = 0;cnt = 0;tag = 0; 95 memset(head, 0, sizeof(head)); 96 memset(g, 0, sizeof(g)); 97 memset(b, 0, sizeof(b)); 98 memset(x, 0, sizeof(x)); 99 memset(y, 0, sizeof(y)); 100 memset(dp, 0, sizeof(dp)); 101 memset(zhuanyi1, 0, sizeof(zhuanyi1)); 102 memset(zhuanyi2, 0, sizeof(zhuanyi2)); 103 memset(zhuanyi3, 0, sizeof(zhuanyi3)); 104 for(register int i = 1;i <= n;++ i) xx[i].clear(), yy[i].clear(); 105 } 106 107 int main() 108 { 109 read(t); 110 for(;t;--t) 111 { 112 read(n); 113 init(); 114 for(register int i = 1;i <= n;++ i) 115 { 116 int tmp; 117 read(tmp); 118 while(tmp) 119 { 120 g[i][tmp] = 1; 121 read(tmp); 122 } 123 } 124 for(register int i = 1;i <= n;++ i) 125 for(register int j = i + 1;j <= n;++ j) 126 if(!g[i][j] || !g[j][i]) 127 insert(i, j), insert(j, i); 128 for(register int i = 1;i <= n;++ i) 129 if(!b[i]) 130 { 131 ++ tot; 132 if(dfs(i, 1)) 133 { 134 printf("No solution "); 135 tag = 1; 136 break; 137 } 138 } 139 if(tag)continue; 140 dp[0][0] = 1; 141 //dp[i][j]表示前i个连通分量,标号为1的有j个是否可行 142 for(register int i = 1;i <= tot;++ i) 143 for(register int j = n;j >= 0;-- j) 144 { 145 if(j - x[i] >= 0 && dp[i - 1][j - x[i]]) 146 { 147 zhuanyi1[i][j] = i - 1; 148 zhuanyi2[i][j] = j - x[i]; 149 zhuanyi3[i][j] = 1; 150 dp[i][j] = 1; 151 } 152 else if(j - y[i] >= 0 && dp[i - 1][j - y[i]]) 153 { 154 zhuanyi1[i][j] = i - 1; 155 zhuanyi2[i][j] = j - y[i]; 156 zhuanyi3[i][j] = 2; 157 dp[i][j] = 1; 158 } 159 } 160 int mid = n/2; 161 if(n & 1) 162 { 163 mid += 1; 164 for(register int i = 0;;++ i) 165 { 166 if(!(i + mid <= n && mid - i > 0)) 167 { 168 tag = 1; 169 break; 170 } 171 if(check(i + mid)) 172 { 173 tag = 1; 174 break; 175 } 176 if(check(mid - i)) 177 { 178 tag = 1; 179 break; 180 } 181 } 182 } 183 else 184 { 185 for(register int i = 1;i <= mid;++i) 186 { 187 if(check(mid - i + 1)) 188 { 189 tag = 1; 190 break; 191 } 192 if(check(mid + i)) 193 { 194 tag = 1; 195 break; 196 } 197 } 198 } 199 if(!tag)printf("No solution "); 200 printf(" "); 201 } 202 return 0; 203 }