GYM 101128 B.Black Vienna (and collection)

Keywords: REST

Description
There are 26 cards A~Z. Now three cards are drawn from them and the remaining 23 cards are divided into players 1 and 2. Now there are n queries. Each time a player is asked if there are two cards and the player's answer is to say that he has several cards in the two cards and to ask how many of the three cards can satisfy these n conditions.
Input
The first line, an integer n, denotes the number of queries. Each query input two characters to denote the two cards to be queried, and the player number to be queried (1or2) and the player's answer (0,1,2) denote how many cards there are in the two players (0<=n<=50).
Output
Number of output legitimate schemes
Sample Input
3
AB 1 1
AC 2 1
BC 2 1
Sample Output
506
Solution
Firstly, deal with the situation of 0 and 2 cards. If there are illegal situations, direct gg. Then the rest is one case. Enumerate three cards and find out whether they are legal. I means that one player holds the first card, i+26 means that two players hold the second card, 0 means that they must take the first card, 0 means that they must take the third card, and 53 means that they must take the third card. For the three cards x, y and z, if one player holds the third card, there are no two choices. Hands do not take these three cards, and then deal with a query involving the three cards x,y,z. Let this query ask a,b, if a,b belong to these three cards, then gg; if not belong to these three cards, then 1 take a and 2 take B together, 2 take a and 1 take B together; if a,b has one belongs to these three cards, then the player must take another card, maybe another card is b, then That is, the current player must take B and the other player must not take b, so that one query can be processed, and then some cards determined to be taken or not taken except x, y and Z can be processed. If both of the I cards must not take or must take, then gg, if one card must take two, then I and 0 will be merged, I + 26 and 53 will be merged, I and 53 will be merged if one must not take two, I + 26 and 0 will be merged. Merge, all merge operations end, judge whether fa[i] and fa[i+26] are the same, if the same description two players have the same card, it is illegal; then judge whether fa[0] and fa[53] are the same, if the same description a player holding a card and not holding a card will merge 0 and 53, unlawful;
Code

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<string>
using namespace std;
#define maxn 55
int fa[maxn];
void init(int n)
{
    for(int i=0;i<=n;i++)fa[i]=i;
}
int find(int x)
{
    if(fa[x]==x)return x;
    return fa[x]=find(fa[x]);
}
void unite(int x,int y)
{
    x=find(x),y=find(y);
    if(x==y)return ;
    fa[x]=y; 
}
int n,q[55][3],res,vis[2][33],mark[2][33],used[55];
char op[5];
bool check(int x,int y,int z)
{
    init(53);
    for(int i=0;i<2;i++)
        for(int j=1;j<=26;j++)
            mark[i][j]=vis[i][j];
    for(int i=0;i<2;i++)
    {
        if(mark[i][x]==1||mark[i][y]==1||mark[i][z]==1)return 0;
        mark[i][x]=mark[i][y]=mark[i][z]=-1;
    }
    for(int i=1;i<=res;i++)
    {
        int f1=0,f2=0,a=q[i][0],b=q[i][1],c=q[i][2];
        if(b==x||b==y||b==z)f1=1;
        if(c==x||c==y||c==z)f2=1;
        if(f1&&f2)return 0;
        if(f2)swap(b,c),swap(f1,f2);
        if(f1)
        {
            int t1=a*26+c,t2=(a^1)*26+c;
            unite(t1,0),unite(t2,53);
        }
        else
        {
            int t1=a*26+b,t2=a*26+c,t3=(a^1)*26+b,t4=(a^1)*26+c;
            unite(t1,t4),unite(t2,t3);
        }
    }
    for(int i=1;i<=26;i++)
        if(i!=x&&i!=y&&i!=z)
        {
            if(mark[0][i]==1&&mark[1][i]==1)return 0;
            if(mark[0][i]==-1&&mark[1][i]==-1)return 0;
            if(mark[0][i]==1||mark[1][i]==-1)unite(i,0),unite(26+i,53);
            else if(mark[1][i]==1||mark[0][i]==-1)unite(i,53),unite(26+i,0);
        }
    if(fa[0]==fa[53])return 0;
    for(int i=1;i<=26;i++)
        if(fa[i]==fa[i+26])return 0;
    return 1;
}
int main()
{
    while(~scanf("%d",&n))
    {
        res=0;
        memset(vis,0,sizeof(vis));
        int gg=0;
        for(int i=1;i<=n;i++)
        {
            int a,b;
            scanf("%s%d%d",op,&a,&b);
            a--;
            int c=op[0]-'A'+1,d=op[1]-'A'+1;
            if(c>d)swap(c,d);
            if(b==0)
            {
                if(vis[a][c]==1||vis[a][d]==1)gg=1;
                else vis[a][c]=vis[a][d]=-1;
            }
            else if(b==2)
            {
                if(vis[a][c]==-1||vis[a][d]==-1)gg=1;
                else vis[a][c]=vis[a][d]=1;
            }
            else q[++res][0]=a,q[res][1]=c,q[res][2]=d;
        }   
        int ans=0;
        if(!gg)
        {
            for(int i=1;i<=26;i++)
                for(int j=i+1;j<=26;j++)
                    for(int k=j+1;k<=26;k++)
                        if(check(i,j,k))ans++;
        }
        printf("%d\n",ans);

    }
    return 0;
}

Posted by dethron on Tue, 16 Apr 2019 09:24:33 -0700