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