UVa 1627 - Team them up!——[0-1背包]
Your task is to divide a number of persons into two teams, in such a way, that:
- everyone belongs to one of the teams;
- every team has at least one member;
- every person in the team knows every other person in his team;
- teams are as close in their sizes as possible.
This task may have many solutions. You are to find and output any solution, or to report that the solution does not exist.
Input
The input begins with a single positive integer on a line by itself indicating the number of the cases following, each of them as described below. This line is followed by a blank line, and there is also a blank line between two consecutive inputs.
For simplicity, all persons are assigned a unique integer identifier from 1 to N.
The first line in the input file contains a single integer number N (2 ≤ N ≤ 100) - the total number of persons to divide into teams, followed by N lines - one line per person in ascending order of their identifiers. Each line contains the list of distinct numbers Aij (1 ≤ Aij ≤ N, Aij ≠ i) separated by spaces. The list represents identifiers of persons that ith person knows. The list is terminated by 0.
Output
For each test case, the output must follow the description below. The outputs of two consecutive cases will be separated by a blank line.
If the solution to the problem does not exist, then write a single message "No solution" (without quotes) to the output file. Otherwise write a solution on two lines. On the first line of the output file write the number of persons in the first team, followed by the identifiers of persons in the first team, placing one space before each identifier. On the second line describe the second team in the same way. You may write teams and identifiers of persons in a team in any order.
Sample Input
2 5
3 4 5 0
1 3 5 0
2 1 4 5 0
2 3 5 0
1 2 3 4 0 5
2 3 5 0
1 4 5 3 0
1 2 5 0
1 2 3 0
4 3 2 1 0
Sample Output
No solution 3 1 3 5
2 2 4 题意分析:
以“不相互认识关系”建无向图,每个连通块都可以分成两队,如果存在已经分成一队的两个人互相不认识,说明无解,表现在图中就是存在环,用bfs求连通块即可。
将每个连通块中必须分到不同队的两组人分别记录下来team0,team1,接下来对求出的各个连通块动态规划,两队人数之差 dt=team0-team1,则要选择将每个连通块适当分组使dt最接近0。
以d(i,j)表示已经选择前i个连通块,且dt=j时的最优解。
状态转移方程为 d(i,j)=min{d(i-1,j-dt[i])+dt[i],d(i-1,j+dt[i]-dt[i])},其中dt[i]是指第i个连通块的两队人数差。
用b(i,j)记录当前状态应该分组的方式,0表示将连通块的team0部分分到0组,1则表示将team0部分分到1组。
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn=;
#define INF 100000000
int know[maxn][maxn];
int unknow[maxn][maxn];
int team[maxn];
int n;
vector<int> block[maxn][];
int num;
int d[maxn][*maxn];
int b[maxn][*maxn];
bool dfs(int i,int t,vector<int> *b){
team[i]=t;
b[t].push_back(i);
bool ok=true;
for(int j=;j<=n;j++){
if(unknow[i][j]){
if(team[j]==-) {
if(!dfs(j,!t,b)){
ok=false;
break;
}
}
else if(team[j]!=t) continue;
else{
ok=false;
break;
}
}
}
return ok;
}
bool blocks(){
for(int i=;i<maxn;i++)
for(int j=;j<;j++)
block[i][j].clear();
num=;
for(int i=;i<=n;i++)
if(team[i]==-)
if(!dfs(i,,block[num++]))
return false;
return true;
}
void dp(){
memset(d, , sizeof d);
memset(b,,sizeof b);
for(int i=;i<=num;i++){
for(int j=;j<*maxn;j++){
if(i==){
d[i][j]=INF;
if(j==maxn)
d[i][j]=;
continue;
}
d[i][j]=INF;
int deta=block[i-][].size()-block[i-][].size();
if(j-deta>=&&j-deta<*maxn&&d[i-][j-deta]!=INF){
if(abs(d[i][j])>abs(d[i-][j-deta]+deta)){
d[i][j]=d[i-][j-deta]+deta;
b[i][j]=;
}
}
if(j+deta>=&&j+deta<*maxn&&d[i-][j+deta]!=INF){
if(abs(d[i][j])>abs(d[i-][j+deta]-deta)){
d[i][j]=d[i-][j+deta]-deta;
b[i][j]=;
}
} }
}
}
void print(){
int ans=INF,p=;
for(int k=;k<*maxn;k++){
if(abs(ans)>abs(d[num][k])){
ans=d[num][k];
p=k;
}
}
vector<int> team[];
for(int i=num,j=p;i>=;i--){
int dt=block[i-][].size()-block[i-][].size();
int t=b[i][j];
if(t==){
for(int k=;k<block[i-][].size();k++)
team[].push_back(block[i-][][k]);
for(int k=;k<block[i-][].size();k++)
team[].push_back(block[i-][][k]);
j-=dt;
}
else{
for(int k=;k<block[i-][].size();k++)
team[].push_back(block[i-][][k]);
for(int k=;k<block[i-][].size();k++)
team[].push_back(block[i-][][k]);
j+=dt;
}
}
printf("%d",int(team[].size()));
for(int i=;i<team[].size();i++){
printf(" %d",team[][i]);
}
printf("\n");
printf("%d",int(team[].size()));
for(int i=;i<team[].size();i++){
printf(" %d",team[][i]);
}
printf("\n");
}
int main(int argc, const char * argv[]) {
int tt;
scanf("%d",&tt);
int cas=;
while(tt--){
memset(know,,sizeof know);
memset(unknow,,sizeof know);
memset(team,-,sizeof team); scanf("%d",&n);
for(int i=;i<=n;i++){
int j;
while(scanf("%d",&j)&&j){
know[i][j]=;
}
} for(int j=;j<=n;j++){
for(int i=;i<=n;i++){
if(i==j)
continue;
if(!know[i][j]){
unknow[i][j]=unknow[j][i]=;
}
}
} if(!blocks()){
printf("No solution\n");
if(tt) printf("\n");
continue;
}
dp();
print();
if(tt) printf("\n");
} return ;
}
UVa 1627 - Team them up!——[0-1背包]的更多相关文章
- 【暑假】[深入动态规划]UVa 1627 Team them up!
UVa 1627 Team them up! 题目: Team them up! Time Limit: 3000MS Memory Limit: Unknown 64bit IO Forma ...
- UVa 1627 Team them up! (01背包+二分图)
题意:给n个分成两个组,保证每个组的人都相互认识,并且两组人数相差最少,给出一种方案. 析:首先我们可以知道如果某两个人不认识,那么他们肯定在不同的分组中,所以我们可以根据这个结论构造成一个图,如果两 ...
- UVA 1627 Team them up!
https://cn.vjudge.net/problem/UVA-1627 题目 有n(n≤100)个人,把他们分成非空的两组,使得每个人都被分到一组,且同组中的人相互认识.要求两组的成员人数尽量接 ...
- UVA.540 Team Queue (队列)
UVA.540 Team Queue (队列) 题意分析 有t个团队正在排队,每次来一个新人的时候,他可以插入到他最后一个队友的身后,如果没有他的队友,那么他只能插入到队伍的最后.题目中包含以下操作: ...
- poj1417 带权并查集+0/1背包
题意:有一个岛上住着一些神和魔,并且已知神和魔的数量,现在已知神总是说真话,魔总是说假话,有 n 个询问,问某个神或魔(身份未知),问题是问某个是神还是魔,根据他们的回答,问是否能够确定哪些是神哪些是 ...
- C:\Windows\system32\config\systemprofile\AppData\Local\Microsoft\Team Foundation\4.0\Cache\VersionControl.config is not valid and cannot be loaded.
Recently, we experienced a strange problem with TFS 2010. We spent a few days before we figured it o ...
- P1417 烹调方案 (0/1背包+贪心)
题目背景 由于你的帮助,火星只遭受了最小的损失.但gw懒得重建家园了,就造了一艘飞船飞向遥远的earth星.不过飞船飞到一半,gw发现了一个很严重的问题:肚子饿了~ gw还是会做饭的,于是拿出了储藏的 ...
- 洛谷 P1064 金明的预算方案 (有依赖的0/1背包)
题目描述 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间.更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过NN元钱就行”. ...
- POJ 1636 Prison rearrangement DFS+0/1背包
题目链接: id=1636">POJ 1636 Prison rearrangement Prison rearrangement Time Limit: 3000MS Memor ...
随机推荐
- JQuery--基础动画、滑动动画、淡入淡出动画、自定义动画
/** * [JQ基础动画] * show() 显示 * hide() 隐藏 * toggle() 切换 * 默认无动画,如果要产生动画 * 在括号内,添加毫秒数,可产生动画和控制动画的快慢 * * ...
- k8s 超详细总结,面试必问
一个目标:容器操作:两地三中心:四层服务发现:五种Pod共享资源:六个CNI常用插件:七层负载均衡:八种隔离维度:九个网络模型原则:十类IP地址:百级产品线:千级物理机:万级容器:相如无亿,K8s有亿 ...
- Directx11教程(43) 纹理映射(13)-动态纹理映射
原文:Directx11教程(43) 纹理映射(13)-动态纹理映射 本篇教程中,我们将在前面基于光照的地形与水面程序里面加上纹理映射,而且我们会基于时间动态改变水面的纹理坐标,实现水面纹理 ...
- keystone同步数据库的时候提示error
keystone 在同步的时候报出以下错误: su -s /bin/sh -c "keystone-manage db_sync" keystone CRITICAL keysto ...
- 块级元素及内联元素对margin、padding的态度
1.块级元素 margin:跟标准一样,设置该块级元素边框与同级兄弟元素或者父元素的距离,俗称外边距. padding:先延伸边框(也就是优先改变元素尺寸而不动元素中内容的位置),当边框碰到父元素的边 ...
- UVa 623 大整数乘法
UVa 623 计算N! n上限为1000自然不能直接算.所以可以开一个数组f[],f[]每一位存N!结果的6位.如果按进制来理解,就是10^6进制: 例如 11!=39916800=11*10!=1 ...
- 阿里大数据产品Dataphin上线公共云,将助力更多企业构建数据中台
日前,由阿里数据打造的智能数据构建与管理Dataphin,重磅上线阿里云-公共云,开启智能研发版本的公共云公测!在此之前,Dataphin以独立部署方式输出并服务线下客户,已助力多家大型客户高效自动化 ...
- js+canvas制作前端验证码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 全站加速(DCDN)- IP应用加速产品解读
5月22日下午15点,阿里云全站加速(DCDN)-IP应用加速如期发布.IP应用加速是阿里云自主研发的一款更高效.更安全.更便捷的动态加速产品,结合阿里云CDN本身的资源优势,利用就近接入.智能路由, ...
- @codeforces - 1205C@ Palindromic Paths
目录 @description@ @solution@ @accepted code@ @details@ @description@ 这是一道交互题. 现在有一个 n*n 的矩阵,每个位置是 0 或 ...