Uva1627 Team them up!

Team them up!

 https://odzkskevi.qnssl.com/9698e76abf2d161889085123803f9464?v=1508663873

 

【题解】

把“两个人不相互认识”连边,形成若干连通分量

不难发现每个联通分量进行黑白染色后,必定选黑或选白

DP[i][j]表示前i个连通块,选j个黑块是否可行

从dp[n][mid]开始向左右检查即可

 

因为边数开小以及偶数n的处理不当RE/WA了很多发

要用大数据测/对拍/手出数据验证程序的每一部分

 

  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("\n%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('\n');
 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\n\n");
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\n");
200         printf("\n");
201     }
202     return 0;
203 }
UVA1627

 

posted @ 2017-10-24 07:27  嘒彼小星  阅读(231)  评论(0编辑  收藏  举报