大型补档计划

题目链接

看到分成两组,想到二分图判定 + 染色。

二分图的特点是两个有矛盾的点连一条边,考虑在这道题中,如果 \(a, b\) 中有一个人不认识对方(或者两个人互不认识),就不可能分在一组,可以在 \((a, b)\) 连一条无向边。

但是由于图不连通,每个联通块染色跑出两种颜色的数量 \(c_1, c_2\) 后(跑不出来无解),让两队数量接近,等价于让一队的数量 $ <= \frac{N}{2}$ 且最大,我们可以把这两个当做一组,把 \(cnt\) 个联通块当做物品,做分组背包选出一队的人员(并且强制选择),因为答案输出任意一组方案,倒序递推出答案即可。

切忌强制转移!因为不强制转移可能出现一组都不选,而题目要求每个队员必须在一队(会 WA 53)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int N = 105;
int n, c1, c2, cnt, col[N], vis[N];
int f[N][N], a[N][N], b[N][N], d[N];
vector<int> ans[2];
bool g[N][N];
bool dfs(int u, int t, int c) {
col[u] = c, vis[u] = t;
c == 1 ? c1++ : c2++;
for (int v = 1; v <= n; v++) {
if (v != u && (!g[u][v] || !g[v][u])) {
if (!col[v]) {
if (!dfs(v, t, 3 - c)) return false;
} else if(col[v] == c) return false;
}
}
return true;
}
void work(int i, int j) {
if (i == 0) return;
if (b[i][j]) d[i] = b[i][j];
work(i - 1, a[i][j]);
}
int main() {
memset(f, 0xcf, sizeof f);
f[0][0] = 0;
scanf("%d", &n);
for (int i = 1, x; i <= n; i++) {
while (scanf("%d", &x), x) {
g[i][x] = true;
}
}
int V = n >> 1;
for (int i = 1; i <= n; i++) {
if (!vis[i]) {
c1 = 0, c2 = 0;
if(!dfs(i, ++cnt, 1)) {
puts("No solution");
return 0;
}
for (int j = V; j >= 0; j--) {
if (j >= c1 && f[cnt - 1][j - c1] + c1 >= f[cnt][j]) {
f[cnt][j] = f[cnt - 1][j - c1] + c1;
a[cnt][j] = j - c1, b[cnt][j] = 1;
}
if (j >= c2 && f[cnt - 1][j - c2] + c2 >= f[cnt][j]) {
f[cnt][j] = f[cnt - 1][j - c2] + c2;
a[cnt][j] = j - c2, b[cnt][j] = 2;
}
}
}
}
int res = 0, t = -1;
for (int i = 0; i <= V; i++)
if (f[cnt][i] > res) res = f[cnt][i], t = i;
work(cnt, t);
for (int i = 1; i <= n; i++) {
if ((col[i] == 1 && d[vis[i]] == 1) || (col[i] == 2 && d[vis[i]] == 2)) ans[0].push_back(i);
else ans[1].push_back(i);
}
for (int i = 0; i < 2; i++) {
printf("%d ", ans[i].size());
for (int j = 0; j < ans[i].size(); j++) printf("%d ", ans[i][j]);
puts("");
}
return 0;
}

最新文章

  1. SharePoint 2016 必备组件离线安装介绍
  2. [C#常用代码]类库中读取解决方案web.Config字符串
  3. hdu 2097
  4. yii 事物
  5. Android Studio 中SDK Manager的设置
  6. OpenSessionInViewFilter 的配置及替代方案(转)
  7. Spring Data JAP 多个不是必填的查询条件处理
  8. 编程实例--for循环,找出0~100之间与8有关的正整数
  9. P1832 A+B Problem(再升级)
  10. iOS基础 - Copy
  11. 修改tomcat图标
  12. transform的影响
  13. Java实现堆排序和计数排序
  14. C# DataTable Lamda GroupBy
  15. How the heck does async/await work in Python 3.5
  16. 牛客JS编程大题(一)
  17. 懒人小工具:T4生成实体类Model,Insert,Select,Delete以及导出Excel的方法
  18. MySQL InnoDB的存储结构总结
  19. MAC CURL : Error:35 SSL certificate problem: Couldn&#39;t understand the server certificate format
  20. vector interators incompatible

热门文章

  1. 聊一聊Token
  2. 编译一个支持多线程的php安装包
  3. linux利用screen进行shell下的屏幕协作
  4. 使用pdfFactory隐藏文档中的隐私信息
  5. css3系列之transform 详解skew
  6. css3系列之详解border-radius
  7. 03生成微博授权URL接口
  8. Java基础教程——多线程:创建线程
  9. Java基础教程——泛型
  10. Centos7.2 安装docker、mysql和redis