【题目描述】
洋葱妹的公司最近与一个跨海相邻国家的修道院签订了业务,洋葱妹被派去与对方接触。
该国家的文化状态非常特别,身为君权神授的宗教国家,却对各种宗教都异常的包容,甚至明明是在同一个修道院里,却能有非常多种类的信仰共存。
洋葱妹想要打点一下关系,他听说修道院里有n个人,于是带了n个不同的礼物,但不同的宗教有着不同的禁忌,宗教A认为礼物A是一种无法饶恕的亵渎,礼物B对宗教B来说则完全不可想象。
洋葱妹在码头的集市找到了一个本地的牙人,打听清楚了各个宗教的禁忌,但即使这样,安排礼物也是一件费心费力的事,你能帮帮她吗?
【输入格式】
第一行两个数n,m,n为修道院人数,m为该注意的禁忌数(n≤11,m≤100)。 接下来m行,每行两个数a和b,表示宗教a不可以接受礼物b。
【输出格式】
输出总的方案数。
样例输入1
2 1
1 2
样例输出1
1
样例输入2
4 3
1 3
2 3
4 3
样例输出2
6
【C++代码】
【解法1】全排列
#include <bits/stdc++.h>
using namespace std;
struct node{
int a,b;
}jin[105];
int main(){
int n,m;
cin>>n>>m;
int re[15];
for(int i=1;i<=n;i++){
re[i]=i;
}
for(int i=1;i<=m;i++){
cin>>jin[i].a>>jin[i].b;
}
int ans=0;
do{
int flag=1;
for(int i=1;i<=m;i++){
if(re[jin[i].a]==jin[i].b){//去掉不可送的
flag=0;
break;
}
}
ans+=flag;
}while(next_permutation(re+1,re+1+n));
cout<<ans;//输出
return 0;
}
【解法2】递归
#include<bits/stdc++.h>
using namespace std;
bool b[12][12];
int n,cnt=0;//不能定义成局部变量
bool vis[12];
long long a[100001];
void f(int x){
if(x>n){
cnt++;
return;
}
for(int i=1;i<=n;i++){
if(!vis[i] &&!b[x][i]){
vis [i]=1;//两种情况:选/不选
f(x+1);
vis [i]=0;
}
}
}
int main(){
int m,x,y;
cin >> n >> m;
while(m--){
cin >> x>> y;
b[x][y]=1;
}
f(1);
cout << cnt;
return 0;
}