牛客练习赛61 C 四个选项(dfs+并查集)

题目链接
链接:https://ac.nowcoder.com/acm/contest/5026/C
来源:牛客网

题目描述
众所周知,高考数学中有一个题目是给出12个单项选择,每一个选择的答案是 A,B,C,D 中的一个。

 网上盛传答案存在某种规律,使得蒙对的可能性大大增加。于是今年老师想让你安排这12个题的答案。但是他有一些条件,首先四个选项的数量必须分别为 na,nb,nc,nd。其次有 m 个额外条件,分别给出两个数字 x,y,代表第 x 个题和第 y 个题的答案相同。 现在你的老师想知道,有多少种可行的方案安排答案。

输入描述:
第一行五个非负整数na,nb,nc,nd,m,保证na+nb+nc+nd=12,0≤m≤1000。

接下来m行每行两个整数x,y(1≤ x,y ≤12)代表第x个题和第y个题答案必须一样。
输出描述:
仅一行一个整数,代表可行的方案数。
示例1
输入

3 3 3 3 0
输出

369600
思路:真是汗颜呀,训练是练的越来越难了,但结果这个C还卡了好久,居然顿时最简单的爆搜也不会搞了,卡了好久QAQ。直接将同分数的用并查集合并,剩下点就是爆搜了。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int father[13],vis[13],a,b,c,d,m,aa=0,bb=0,cc=0,dd=0,ans=0;
int findfather(int x)
{
    if(x==father[x]) return x;
    int i=findfather(father[x]);
    father[x]=i;
    return i;
 }
 void unit(int x,int y)
 {
    int fa=findfather(x),fb=findfather(y);
    if(fa!=fb)
    {
        father[fa]=fb;
    }
 }
void dfs(int x)
{
    if(x==13) {
        ans++;return ;
    }
    if(vis[x]==0) dfs(x+1);
    else{
        if(aa+vis[x]<=a) aa+=vis[x],dfs(x+1),aa-=vis[x];
        if(bb+vis[x]<=b) bb+=vis[x],dfs(x+1),bb-=vis[x];
        if(cc+vis[x]<=c) cc+=vis[x],dfs(x+1),cc-=vis[x];
        if(dd+vis[x]<=d) dd+=vis[x],dfs(x+1),dd-=vis[x];
    }
}
int main()
{
    scanf("%d %d %d %d %d",&a,&b,&c,&d,&m);
    for(int i=0;i<=12;++i) father[i]=i;
    for(int i=1,x,y;i<=m;++i) {
        scanf("%d %d",&x,&y);
        unit(x,y);
    }
    for(int i=1;i<=12;++i) vis[findfather(i)]++;
    dfs(1);
    cout<<ans<<endl;
}
发布了391 篇原创文章 · 获赞 1 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_42479630/article/details/105458329