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背包]的更多相关文章

  1. 【暑假】[深入动态规划]UVa 1627 Team them up!

    UVa 1627 Team them up! 题目: Team them up! Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Forma ...

  2. UVa 1627 Team them up! (01背包+二分图)

    题意:给n个分成两个组,保证每个组的人都相互认识,并且两组人数相差最少,给出一种方案. 析:首先我们可以知道如果某两个人不认识,那么他们肯定在不同的分组中,所以我们可以根据这个结论构造成一个图,如果两 ...

  3. UVA 1627 Team them up!

    https://cn.vjudge.net/problem/UVA-1627 题目 有n(n≤100)个人,把他们分成非空的两组,使得每个人都被分到一组,且同组中的人相互认识.要求两组的成员人数尽量接 ...

  4. UVA.540 Team Queue (队列)

    UVA.540 Team Queue (队列) 题意分析 有t个团队正在排队,每次来一个新人的时候,他可以插入到他最后一个队友的身后,如果没有他的队友,那么他只能插入到队伍的最后.题目中包含以下操作: ...

  5. poj1417 带权并查集+0/1背包

    题意:有一个岛上住着一些神和魔,并且已知神和魔的数量,现在已知神总是说真话,魔总是说假话,有 n 个询问,问某个神或魔(身份未知),问题是问某个是神还是魔,根据他们的回答,问是否能够确定哪些是神哪些是 ...

  6. 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 ...

  7. P1417 烹调方案 (0/1背包+贪心)

    题目背景 由于你的帮助,火星只遭受了最小的损失.但gw懒得重建家园了,就造了一艘飞船飞向遥远的earth星.不过飞船飞到一半,gw发现了一个很严重的问题:肚子饿了~ gw还是会做饭的,于是拿出了储藏的 ...

  8. 洛谷 P1064 金明的预算方案 (有依赖的0/1背包)

    题目描述 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间.更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过NN元钱就行”. ...

  9. POJ 1636 Prison rearrangement DFS+0/1背包

    题目链接: id=1636">POJ 1636 Prison rearrangement Prison rearrangement Time Limit: 3000MS   Memor ...

随机推荐

  1. node.js对象数据类型

    在这里复习下前端JS的数据类型:前端JS中的数据类型: 1.基本/原生/值类型 string.number.boolean.null.undefined 2.引用/对象类型    ES对象类型:Str ...

  2. Polyfill简介

    1.什么是Polyfill? Polyfill是一个js库,主要抚平不同浏览器之间对js实现的差异.比如,html5的storage(session,local), 不同浏览器,不同版本,有些支持,有 ...

  3. 操作系统之LRU算法 C语言链表实现

    LRU是Least Recently Used的缩写,即最近最少使用,是一种常用的页面置换算法,选择最近最久未使用的页面予以淘汰.该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历 ...

  4. 【C++】反向迭代器(rbegin,rend)(转载)

    转自:http://blog.csdn.net/kjing/article/details/6936325 rbegin和rend,很有用! C++ primer (中文版第四版)第273页 9.3. ...

  5. JAVA代码规范 标签: java文档工作 2016-06-12 21:50 277人阅读 评论(5) 收藏

    开始做java的ITOO了,近期的工作内容就是按照代码规范来改自己负责的代码,之前做机房收费系统的时候,也是经常验收的,甚至于我们上次验收的时候,老师也去了.对于我们的代码规范,老师其实是很重视的,他 ...

  6. SDUT-2130_数据结构实验之数组一:矩阵转置

    数据结构实验之数组一:矩阵转置 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 数组--矩阵的转置 给定一个m*n的矩阵 ...

  7. Java练习 SDUT-3422_小金问呀问不会问题

    小金问呀问不会问题 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 众所周知,C语言的学习是我们程序设计基础的重点和主要 ...

  8. WebLogic Server再曝高风险远程命令执行0day漏洞,阿里云WAF支持免费应急服务

    6月11日,阿里云安全团队发现WebLogic CVE-2019-2725补丁绕过的0day漏洞,并第一时间上报Oracle官方, 6月12日获得Oracle官方确认.由于Oracle尚未发布官方补丁 ...

  9. 当better-scroll遇见了react擦出的火花

    关于better-scroll这个插件前面已经介绍过两次了 从原生js使用到结合服务端发送数据使用都有过介绍 今天给大家分享一下这款插件在react中遇见的坑  总之我真是对这款插件又爱又恨 每次各种 ...

  10. MapReduce数据流-Partiton&Shuffle