题意
总共12道题,以A,B,C,D为答案的有na,nb,nc,nd个,且有一些题目答案要一致。
思路
答案一致想到并查集合并到一起,然后我就很蠢的开始想排列组合了,后来发现排列组合的情况很多,不好写,遂开始思考dp,发现还是不会,这时候瞟了一眼数据,这个数据范围很小,直接暴力模拟利用stl中的next_permutation模拟,若符合条件则计数即可,跑了一下
。
咦,大家怎么都是dfs做的呢?其实dfs和next_permutation在这里应该都是一样的吧,我中间好像也想过用dfs。
代码虽然看起来很长,但我觉得思路很好,不用动啥脑子,暴力就是了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const double eps = 1e-8;
const int NINF = 0xc0c0c0c0;
const int INF = 0x3f3f3f3f;
const ll mod = 1e9 + 7;
const ll maxn = 1e6 + 5;
const ll MAXN = 1e6 + 5;
const int N = 15;
ll m,n[5];
int f[N],a[N];
void init(int n){
for(int i=0;i<=n;i++) f[i]=i;
return;
}
int find(int x){
return f[x]==x?x:f[x]=find(f[x]);//路径压缩
}
void merge(int x, int y){
int a=find(x);
int b=find(y);
if(a!=b) f[b]=a;//“靠左”原则
return;
}
vector<int>G[N];
bool check(){
for(int i=1;i<=12;i++){
if(f[i]==i){
for(auto c:G[i]){
if(a[c]==a[i]) continue;
else return false;
}
}
}
return true;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n[1]>>n[2]>>n[3]>>n[4]>>m;
init(12);
while(m--){
int x,y;
cin>>x>>y;
merge(x,y);
}
for(int i=1;i<=12;i++){
if(f[i]==i) continue;
else G[find(i)].push_back(i);
}
int tot=0;
for(int i=1;i<=4;i++){
int k=n[i];
while(k>0) a[++tot]=i,k--;
}
sort(a+1,a+1+12);
int sum=0;
do
{
if(check()) sum++;
}while(next_permutation(a+1,a+1+12));
cout<<sum<<'\n';
return 0;
}
京公网安备 11010502036488号