按照紫书的思路,首先分组,然后依次“遍历”所有的分组方式(典型的空间换时间),得到最终的结果,具体实现见如下代码:
#include<iostream>
#include<vector>
#include<string>
#include<set>
#include<stack>
#include<queue>
#include<map>
#include<algorithm>
#include<cmath>
#include<iomanip>
#include<cstring>
#include<sstream>
#include<cstdio>
#include<deque>
using namespace std;
int M,N;
int edge[110][110];
int color[110];
int plan[110][300];
struct Record{
vector<int> group[2];
void clear(){
group[0].clear();
group[1].clear();
}
};
vector<Record> record;
Record temp;
bool dfs(int ind,int flag){
color[ind] = flag;
for (int i = 0; i < N; i++){
if (i != ind){
if (!(edge[ind][i] && edge[i][ind])){
if (!color[i] && !dfs(i, -flag)) return false;
if (color[ind] == color[i]) return false;
}
}
}
if (flag == 1) temp.group[0].push_back(ind);
else temp.group[1].push_back(ind);
return true;
}
void copyTo(vector<int>& a,vector<int>& b){
for (int i = 0; i < a.size(); i++) b.push_back(a[i]);
}
void Print(int j){
vector<int> result[2];
for (int i = record.size() - 1; i >= 0; i--){
int dis = record[i].group[0].size() - record[i].group[1].size();
if (plan[i][j] == 1){
copyTo(record[i].group[0], result[0]);
copyTo(record[i].group[1], result[1]);
j -= dis;
}
else if (plan[i][j] == -1){
copyTo(record[i].group[0], result[1]);
copyTo(record[i].group[1], result[0]);
j += dis;
}
}
cout << result[0].size();
for (int i = 0; i < result[0].size(); i++){
cout << " " << result[0][i]+1;
}
cout << endl;
cout << result[1].size();
for (int i = 0; i < result[1].size(); i++){
cout << " " << result[1][i]+1;
}
cout << endl;
}
void solve(){
for (int i = 0; i < record.size(); i++){
int dis = record[i].group[0].size() - record[i].group[1].size();
for (int j = 0; j <= 2 * N; j++){
if (i == 0){
plan[i][N + dis] = 1;
plan[i][N - dis] = -1;
break;
}
else{
if (plan[i - 1][j]){
plan[i][j + dis] = 1;
plan[i][j - dis] = -1;
}
}
}
}
int ind = record.size() - 1;
for (int j = 0; j <= N; j++){
if (plan[ind][N + j]){
Print(N+j);
return;
}
if (plan[ind][N - j]){
Print(N - j);
return;
}
}
}
int main(){
cin >> M;
while (M--){
cin >> N;
record.clear();
memset(edge,0,sizeof(edge));
memset(color, 0, sizeof(color));
for (int i = 0; i < N; i++){
int b;
while (cin >> b&&b) edge[i][b-1] = 1;
}
bool feasible = true;
for (int i = 0; i < N;i++){
temp.clear();
if (!color[i]){
if (!dfs(i, 1)){
feasible = false;
break;
}
record.push_back(temp);
}
}
memset(plan,0,sizeof(plan));
if (!feasible){
cout << "No solution\n";
}
else{
solve();
}
if (M) cout << "\n";
}
return 0;
}