引用discuss里的一句话,好辣的一道题目。。。
一定要注意认识的关系不是互相的,先建图,把不是互相认识的人连边,然后二分图染色,把原图分成m个块,再用类似背包的东西分f[i][j][k]表示前i个块,team1有j个人,team2有k个人能否实现,注意记录一下路径,然后递归输出就可以了,题目不算很难,但是细节比较多,涉及到的东西也挺多,挺容易出错的。。。


1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<vector> 6 #include<stack> 7 #include<queue> 8 #include<map> 9 #include<cstdlib> 10 #include<cmath> 11 using namespace std; 12 #define ll long long 13 #define pb push_back 14 const int maxn = 102; 15 vector<int>q[maxn]; 16 bool s[maxn]; 17 int a[maxn][4]; 18 vector<int>b[maxn][4]; 19 int t[maxn],g[maxn][maxn][maxn]; 20 int m,n; 21 bool v[maxn][maxn],e[maxn][maxn]; 22 bool f[maxn][maxn][maxn]; 23 void solve(int x,int y) 24 { 25 for (int i = 0; i < q[x].size(); i++) 26 if (s[q[x][i]] == 0) 27 { 28 s[q[x][i]] = 1; 29 a[m][y]++; 30 b[m][y].pb(q[x][i]); 31 solve(q[x][i],3 - y); 32 } 33 } 34 void dfs(int now,int x,int y) 35 { 36 if (now == 0) return; 37 t[now] = g[now][x][y]; 38 if (t[now] == 1) dfs(now - 1,x - a[now][1],y - a[now][2]); 39 else dfs(now - 1,x - a[now][2],y - a[now][1]); 40 } 41 bool check(int x,int y) 42 { 43 for (int i = 0; i < b[x][y].size(); i++) 44 for (int j = 0; j < b[x][y].size(); j++) 45 if (b[x][y][i] != b[x][y][j] && e[b[x][y][i]][b[x][y][j]]) return 1; 46 return 0; 47 } 48 int main() 49 { 50 while (scanf("%d",&n) != EOF) 51 { 52 for (int i = 1; i <= n; i++) q[i].clear(); 53 memset(v,0,sizeof(v)); 54 memset(e,0,sizeof(e)); 55 int x; 56 for (int i = 1; i <= n; i++) 57 { 58 while (scanf("%d",&x) && x != 0) v[i][x] = 1; 59 } 60 //for (int i = 1; i <= n;i++) 61 //for (int j = 1; j <= n; j++) if (v[i][j]) cout<<i<<" "<<j<<endl; 62 //return 0; 63 for (int i = 1; i <= n; i++) 64 for (int j = i + 1; j <= n; j++) 65 { 66 if (v[i][j] && v[j][i]) continue; 67 q[i].pb(j); 68 q[j].pb(i); 69 e[i][j] = e[j][i] = 1; 70 } 71 /*for (int i = 1; i<= n; i++) 72 { 73 cout<<i<<" "; 74 for (int j = 0; j < q[i].size(); j++) cout<<q[i][j]<<" "; 75 cout<<endl; 76 }*/ 77 //return 0; 78 memset(s,0,sizeof(s)); 79 memset(s,0,sizeof(s)); 80 memset(a,0,sizeof(a)); 81 m = 0; 82 for (int i = 1; i <= n; i++) 83 for (int j = 1; j <= 2; j++) b[i][j].clear(); 84 for (int i = 1; i <= n; i++) 85 if (s[i] == 0) 86 { 87 s[i] = 1; 88 m++; 89 a[m][1]++; 90 b[m][1].pb(i); 91 solve(i,2); 92 } 93 bool flag = 0; 94 for (int i = 1; i <= m; i++) 95 { 96 if (check(i,2) || check(i,1)) 97 { 98 flag = 1; 99 break; 100 } 101 } 102 if (flag) 103 { 104 puts("No solution"); 105 continue; 106 } 107 memset(f,0,sizeof(f)); 108 memset(g,0,sizeof(g)); 109 f[0][0][0] = 1; 110 //return 0; 111 for (int i = 1; i <= m; i++) 112 for (int j = 0; j <= n; j++) 113 for (int k = 0; k <= n; k++) 114 if (j + k <= n) 115 { 116 if (j - a[i][1] >= 0 && k - a[i][2] >= 0 && f[i - 1][j - a[i][1]][k - a[i][2]]) 117 { 118 f[i][j][k] = 1; 119 g[i][j][k] = 1; 120 } 121 if (j - a[i][2] >= 0 && k - a[i][1] >= 0 && f[i - 1][j - a[i][2]][k - a[i][1]]) 122 { 123 f[i][j][k] = 1; 124 g[i][j][k] = 2; 125 } 126 } 127 int maxx = 10000,fir = 0,sec = 0; 128 for (int i = 1; i <= n - 1; i++) 129 { 130 int j = n - i; 131 if (f[m][i][j] && maxx > abs(i - j)) 132 { 133 maxx = abs(i - j); 134 fir = i; sec = j; 135 } 136 } 137 memset(t,0,sizeof(t)); 138 dfs(m,fir,sec); 139 memset(s,0,sizeof(s)); 140 int ans = 0; 141 for (int i = 1; i <= m; i++) 142 if (t[i] == 1) 143 { 144 ans = ans + b[i][1].size(); 145 for (int j = 0; j < b[i][1].size(); j++) s[b[i][1][j]] = 1; 146 } 147 else 148 { 149 ans = ans + b[i][2].size(); 150 for (int j = 0; j < b[i][2].size(); j++) s[b[i][2][j]] = 1; 151 } 152 if (ans == n || ans == 0) 153 { 154 puts("No solution"); 155 continue; 156 } 157 printf("%d",ans); 158 for (int i = 1; i <= n; i++) 159 if (s[i]) printf(" %d",i); 160 printf("\n"); 161 printf("%d",n - ans); 162 for (int i = 1; i <= n; i++) 163 if (!s[i]) printf(" %d",i); 164 printf("\n"); 165 } 166 return 0; 167 }