[ABC310D] Peaceful Teams
题面翻译
有 N N N 位运动员,其中 A i A_i Ai 与 B i B_i Bi ( 1 ≤ i ≤ M 1 \le i \le M 1≤i≤M)两人不能在同一小组,现在,我们给定小组数 T T T 请你分配他们到任意一个小组。注意小组不能为空。请求出所有不同的方案的数量。
题目描述
$ N $ 人のスポーツ選手がいます。
$ N $ 人の選手たちには互いに相性の悪い選手のペアが $ M $ 組あり、相性の悪い組のうち $ i\ (1\leq\ i\leq\ M) $ 組目は $ A\ _\ i $ 番目の選手と $ B\ _\ i $ 番目の選手です。
あなたは、選手を $ T $ チームに分けます。 どの選手もちょうど一つのチームに属さなければならず、どのチームにも少なくとも一人の選手が属さなければなりません。 さらに、どの $ i=1,2,\ldots,M $ についても、 $ A\ _\ i $ 番目の選手と $ B\ _\ i $ 番目の選手が同じチームに属していてはいけません。
この条件を満たすチーム分けの方法は何通りあるか求めてください。 ただし、チーム分けの方法が異なるとは、ある二人が存在して、彼らが一方のチーム分けでは同じチームに所属し、もう一方では異なるチームに所属することをいいます。
输入格式
入力は以下の形式で標準入力から与えられる。
$ N $ $ T $ $ M $ $ A\ _\ 1 $ $ B\ _\ 1 $ $ A\ _\ 2 $ $ B\ _\ 2 $ $ \vdots $ $ A\ _\ M $ $ B\ _\ M $
输出格式
答えを $ 1 $ 行で出力せよ。
样例 #1
样例输入 #1
5 2 2
1 3
3 4
样例输出 #1
4
样例 #2
样例输入 #2
5 1 2
1 3
3 4
样例输出 #2
0
样例 #3
样例输入 #3
6 4 0
样例输出 #3
65
样例 #4
样例输入 #4
10 6 8
5 9
1 4
3 8
1 6
4 10
5 7
5 6
3 7
样例输出 #4
8001
提示
制約
- $ 1\leq\ T\leq\ N\leq10 $
- $ 0\leq\ M\leq\dfrac{N(N-1)}2 $
- $ 1\leq\ A\ _\ i\lt\ B\ _\ i\leq\ N\ (1\leq\ i\leq\ M) $
- $ (A\ _\ i,B\ _\ i)\neq\ (A\ _\ j,B\ _\ j)\ (1\leq\ i\lt\ j\leq\ M) $
- 入力はすべて整数
Sample Explanation 1
次の $ 4 $ 通りのチーム分けが条件を満たします。 ![](https://img.atcoder.jp/abc310/b92c2629f68d56350fe18e6d0a8fa060.png) 他に条件を満たすチーム分けは存在しないので、$ 4 $ を出力してください。
Sample Explanation 2
条件を満たすチーム分けがひとつも存在しないこともあります。
Sample Explanation 3
相性の悪いペアがひとつも存在しないこともあります。
思路
首先从输入中读取运动员的数量、组的数量和冲突的数量。然后,对于每个冲突,读取两个有冲突的运动员的编号,并在二维bitset数组cf
中标记这个冲突。
接下来,执行深度优先搜索来枚举所有可能的分组方案。在每一步中,尝试将当前的运动员加入到一个已有的组中,或者创建一个新的组。在每种尝试中,检查是否会导致冲突。如果会导致冲突,跳过这种尝试。如果不会导致冲突,递归地对下一个运动员进行同样的处理。
在深度优先搜索的过程中,使用一个计数器tcnt
记录当前已经创建的组的数量。当所有的运动员都被处理完毕后,如果已经创建的组的数量等于预期的组的数量,说明找到一个有效的分组方案,此时返回1,否则返回0。
最后,将所有返回的值累加起来,就得到所有可能的分组方案的数量。输出这个数量,就得到问题的答案。
AC代码
#include <bitset>
#include <iostream>
#include <unordered_set>
#define AUTHOR "HEX9CF"
using namespace std;
using ll = long long;
const int N = 15;
// 人数、队伍数、冲突数
int n, t, m;
int tcnt;
bitset<N> cf[N];
unordered_set<int> team[N];
ll dfs(int d) {
if (d == n + 1) {
return (ll)(tcnt == t);
}
ll r = 0;
// 加入已有队伍
for (int i = 1; i <= tcnt; i++) {
// 检测冲突
bool flg = 0;
for (const auto j : team[i]) {
if (cf[d][j]) {
flg = 1;
break;
}
}
if (flg) {
continue;
}
team[i].insert(d);
r += dfs(d + 1);
team[i].erase(d);
}
// 创建新队伍
team[++tcnt].insert(d);
r += dfs(d + 1);
team[tcnt--].erase(d);
return r;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
tcnt = 0;
cin >> n >> t >> m;
for (int i = 1; i <= m; i++) {
int a, b;
cin >> a >> b;
cf[a][b] = cf[b][a] = 1;
}
cout << dfs(1) << "\n";
return 0;
}