题意

总共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;
}