• Gym 101128 B Black Vienna


    题意

    有A-Z 26张牌,现在从中抽出3张牌,并把剩下的23张牌分给选手1和2,现在有n次询问,每次询问一个选手是否有某两张牌,和选手的回答。回答说自己有这两张牌中的几张,问拿出的三张牌有多少种方案能够满足这n个条件?n<=50

    分析

    个人感觉这个题是个很不错的题呢。

    并查集的应用,有点像那道“关押罪犯”的升级版?www.cnblogs.com/LQLlulu/p/8819599.html

    数据很小,只有26张牌和50个询问。那么三重循环枚举抽哪三张牌。对于每次抽出的三张牌,判断一下能否满足这n个询问,如果满足的话ans++。

    但是怎么判断?

    因为只有两个玩家,那么对于每张牌,如果这张牌没有被抽走,那么要么属于玩家1,要么属于玩家2。对于大多数情况我们都可以通过记录每张牌的归属判断是否冲突。

    但是有一种特殊情况:

    此时两张牌都未被抽走,而且回答是1。也就是说,这两张牌里有一张是属于这个人,另一张属于另一个玩家。那么我们此时没法直接记录。因为我们并不能知道哪张牌属于谁,只能确定这两张牌不属于同一个人!没错!这句话表明了要用并查集!

    对于每个上述的情况:x=find(a),y=find(b),如果x和y相等说明两者在同一个人手中,那么直接返回false,否则的话我们把他们和另一个的补集相连,p[x]=find(b+n),p[y]=find(a+n)。这代表两者不在同一个集合(因为只有两个集合,所以满足敌人的敌人就是朋友)。

    然后对于每个并查集就分给一个人,判断是否会冲突,如果冲突返回false。

    如果上述都没有冲突,则返回true。

      1 #include <cstdio>
      2 #include <algorithm>
      3 #include <cstring>
      4 #include <iostream>
      5 
      6 using namespace std;
      7 const int maxn=100+10;
      8 int n;
      9 int p[maxn];
     10 struct Node{
     11     char s[2];
     12     int who;
     13     int num;
     14 }node[maxn];
     15 int ans;
     16 int Wh[maxn],val[maxn];
     17 int find(int x){
     18     return p[x]==x?x:p[x]=find(p[x]);
     19 }
     20 bool check(int A,int B,int C){
     21     for(int i=1;i<=60;i++)p[i]=i;
     22     memset(Wh,-1,sizeof(Wh));
     23     bool ok=1;
     24     for(int i=1;i<=n;i++){
     25         int a=node[i].s[0]-'A'+1;
     26         int b=node[i].s[1]-'A'+1;
     27         int w=node[i].who;
     28       //  cout<<a<<" "<<b<<" "<<node[i].num<<endl;
     29 
     30         if(node[i].num==2){
     31             if(a==A||a==B||a==C||b==A||b==B||b==C){
     32                 //cout<<"-1"<<endl;
     33                 ok=0;
     34                 break;
     35             }
     36             if((Wh[a]==(w^1))||(Wh[b]==(w^1))){
     37                 ok=0;
     38                 break;
     39             }
     40            // cout<<-1<<endl;
     41             Wh[a]=w,Wh[b]=w;
     42         }
     43         if(node[i].num==0){
     44             if((a==A||a==B||a==C)&&(b==A||b==B||b==C))
     45                 continue;
     46             else if(a==A||a==B||a==C){
     47                 if(Wh[b]==w){
     48                     ok=0;
     49                     break;
     50                 }
     51                 Wh[b]=(w^1);
     52             }
     53             else if(b==A||b==B||b==C){
     54                 if(Wh[a]==w){
     55                     ok=0;
     56                     break;
     57                 }
     58                 Wh[a]=(w^1);
     59             }
     60             else{
     61                 if(Wh[a]==w||Wh[b]==w){
     62                     ok=0;
     63                     break;
     64                 }
     65                 Wh[a]=(w^1),Wh[b]=(w^1);
     66             }
     67         }
     68         if(node[i].num==1){
     69             if((a==A||a==B||a==C)&&(b==A||b==B||b==C)){
     70                 ok=0;
     71                 break;
     72             }
     73             else if(a==A||a==B||a==C){
     74                 if(Wh[b]==(w^1)){
     75                     ok=0;
     76                     break;
     77                 }
     78                 Wh[b]=w;
     79             }
     80             else if(b==A||b==B||b==C){
     81                 if(Wh[a]==(w^1)){
     82                     ok=0;
     83                     break;
     84                 }
     85                 Wh[a]=w;
     86             }else{
     87                 int x=find(a),y=find(b);
     88                 if(x==y){
     89                     ok=0;
     90                     break;
     91                 }
     92                 p[x]=find(b+26);
     93                 p[y]=find(a+26);
     94             }
     95         }
     96     }
     97     if(!ok)return false;
     98 
     99     memset(val,-1,sizeof(val));
    100     for(int i=1;i<=26;i++){
    101         if(Wh[i]!=-1){
    102             int f=find(i);
    103             if(val[f]==
    104                (Wh[i]^1)){
    105                 ok=0;
    106               //  cout<<-1<<endl;
    107                 break;
    108             }
    109             val[f]=Wh[i];
    110             f=find(i+26);
    111            // cout<<Wh[i]<<endl;
    112             if(val[f]==Wh[i]){
    113                // cout<<val[f]<<" "<<Wh[i]<<endl;
    114                 ok=0;
    115                 break;
    116             }
    117             val[f]=(Wh[i]^1);
    118         }
    119     }
    120     if(!ok)return false;
    121 
    122     for(int i=1;i<=26;i++){
    123         int x=find(i),y=find(i+26);
    124         if(x==y||(val[x]==val[y]&&val[x]!=-1)){
    125             ok=0;
    126             break;
    127         }
    128     }
    129     if(!ok)return false;
    130     return true;
    131 }
    132 int main(){
    133     ans=0;
    134     scanf("%d",&n);
    135     for(int i=1;i<=n;i++){
    136         scanf("%s%d%d",node[i].s,&node[i].who,&node[i].num);
    137         node[i].who--;
    138     }
    139 
    140     for(int i=1;i<=26;i++){
    141         for(int j=i+1;j<=26;j++){
    142             for(int k=j+1;k<=26;k++){
    143                 if(check(i,j,k))
    144                     ans++;
    145             }
    146         }
    147     }
    148     cout<<ans;
    149 return 0;
    150 }
    View Code
  • 相关阅读:
    科普下病菌和病毒
    centos环境下安装docker
    change master to到一个不存在的主库或主库无法连接
    java.lang.outofmemoryerror android
    委托 C#
    将PC端的网站转化成手机端网站需要增加以下这段代码即可,再布局一下界面即可
    combobox联动
    删除dataGridview中选中的一行或多行
    vs2010下如何使【“System.Data.OracleClient.OracleConnection”已过时】 解决办法
    MyEclipse连接SQL Server 2008数据库的操作方法
  • 原文地址:https://www.cnblogs.com/LQLlulu/p/8824803.html
Copyright © 2020-2023  润新知