HOJ 13813 Blood groups

Blood groups
Time Limit: 2000ms, Special Time Limit:5000ms, Memory Limit:131072KB
Total submit users: 2, Accepted users: 2
Problem 13813 : No special judgement
Problem description
There are four possible blood groups for humans: AB, A, B and O, meaning that the red blood cells have antigens of types, respectively, A and B, only A, only B, and no antigen at all. Our blood group is determined by two alleles in our DNA. Each allele is of type either A, B or O. The following table lists the possible allele combinations someone may have for each blood group:


We inherit exactly one allele from each of our two parents. So, given the blood groups of the two parents, we can say for sure if some blood group is possible, or not, in their offspring. For example, if the blood groups of the two parents are AB and B, then the possible allele combinations for them are, respectively, {AB} and {OB,BB}. Since the order of the alleles does not matter, the possible allele combinations for the offspring are {OA,AB,OB,BB}. That means the blood groups AB, A and B are possible in their offspring, but the blood group O is not. Very nice indeed! But what if life on Earth had evolved so that a person had three parents, three alleles, and three different antigen types? The allele combinations would look like this: 

If the blood groups of the three parents are A, BC and O, then all blood groups are possible in their offspring, except groups BC and ABC.
The universe is vast! There may be, out there in space, some form of life whose individuals have N parents, N alleles, and N different antigen types. Given the blood groups for the N parents, and a list of Q blood groups to test, your program has to determine which ones are possible, and which ones are not, in the offspring of the given parents.


Input
The first line contains two integers N and Q, representing respectively the number of parents (and alleles, and antigen types) and the number of queries (1 ≤ N ≤ 100 and 1 ≤ Q ≤ 40). Each of the next N lines describes the blood group of a parent. After that, each of the next Q lines describes a blood group to test. Antigen types are identified with distinct integers from 1 to N, not letters. Each line describing a blood group contains an integer B indicating the number of antigen types in the blood group (0 ≤ B ≤ N), followed by B different integers C1,C2,...,CB representing the antigen types present in the blood group (1 ≤ Ci ≤ N for i = 1,2,...,B). 


Output
For each of the Q queries, output a line with the uppercase letter "Y" if the corresponding blood group is possible in the offspring of the given parents; otherwise output the uppercase letter "N". Write the results in the same order that the queries appear in the input. 



Sample Input
Sample input 1
2 1
2 2 1
1 2
0

Sample input 2
3 4
1 1
2 2 3
0
1 3
3 2 1 3
2 1 2
2 3 2

Sample input 3
4 3
4 2 1 3 4
4 2 1 3 4
1 1
1 2
1 3
2 2 1
0
Sample Output
Sample output 1
N

Sample output 2
Y
N
Y
N

Sample output 3
Y
Y
N

题意:某星球n个父母亲可以携带有某些基因,有显性基因和隐性基因,可以遗传给子女。每个父母亲每个可以遗传给子女一个基因,并且也只能遗传一个基因给子女。题目给出n个父母的基因和q次询问,如果给出的子女的基因是合法的(可以由给出的父母遗传给子女)输出Y,否则输出N。

题解:没想到的匹配,二分图的最大匹配。给出了父母的基因,每个父母可以提供显性和隐性基因,并且基因的长度是n(每个父母当且仅当提供一个)。因此用到二分图的最大匹配,父母的基因构成一个点集,子女的构成一个点集。这样就会考虑子女的需要的基因,需要的基因与父母可以给的基因连边(注意是n个基因),建图。然后进行二分匹配(匈牙利算法)就可以搞定了,如果得到的最大匹配等于n,则是每个子女的基因都被匹配,则输出Y。

详见代码:

#include <stdio.h>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <vector>
#include <queue>
#include <stack>
#include <iostream>
#define pi acos(-1.0)
#define INF 0x3f3f3f3f
using namespace std;
#define ll long long
const int maxn=110;
int n;
int g[maxn][maxn];
int mach[maxn],ch[maxn];
bool dfs(int u)
{
    for(int i=0;i<=n;i++)
        if(!ch[i]&&g[u][i])
        {
            ch[i]=1;
            if(mach[i]==-1||dfs(mach[i]))
            {
                mach[i]=u;
                return true;
            }
        }
    return false;
}
int maxmach()
{
    int ans=0;
    memset(mach,-1,sizeof(mach));
    for(int i=1;i<=n;i++)
    {
        memset(ch,0,sizeof(ch));
        if(dfs(i))
            ans++;
    }
    return ans;
}
int mmp[maxn][maxn];
int  main()
{
    //freopen("C:\\Users\\Administrator\\Desktop\\a.txt","r",stdin);
    //ios::sync_with_stdio(false);
    //freopen("C:\\Users\\Administrator\\Desktop\\b.txt","w",stdout);
    int q;
    while(scanf("%d%d",&n,&q)!=EOF)
    {
        memset(mmp,0,sizeof(mmp));
        for(int i=1;i<=n;i++)
        {
            int t,t1;
            scanf("%d",&t);
            if(t<n) mmp[i][0]=1;
            while(t--)
            {
                scanf("%d",&t1);
                mmp[i][t1]=1;
            }
        }
//        cout<<"mmp"<<endl;
//        for(int i=0;i<=n;i++)
//        {
//            for(int j=0;j<=n;j++)
//            printf("%d ",mmp[i][j]);
//            cout<<endl;
//        }
        int Ans=0;
        for(int j=0;j<q;j++)
        {
            memset(g,0,sizeof g);
            int t,t1;
            scanf("%d",&t);
            if(t==0)
            {
                for(int i=1;i<=n;i++)
                {
                    if(mmp[i][0])
                    {
                        int kk=1;
                        while(kk<=n)
                        {
                            g[i][kk]=1;
                            kk++;
                        }
                    }
                }
            }
            for(int k=1;k<=t;k++)
            {
                scanf("%d",&t1);
                for(int i=1;i<=n;i++)
                {
                    if(mmp[i][t1])
                    {
                        g[i][k]=1;
                        for(int kk=t+1;kk<=n;kk++)
                            g[i][kk]=1;
                    }
                    if(t<n&&mmp[i][0])
                    {
                        for(int kk=t+1;kk<=n;kk++)
                         g[i][kk]=1;
                    }
                }
            }
//            cout<<"j "<<j<<endl;
//            for(int i=0;i<=n;i++)
//            {
//                for(int j=0;j<=n;j++)
//                printf("%d ",g[i][j]);
//                cout<<endl;
//            }
//            for(int i=0;i<=n;i++)
//                printf("vis %d ",vis[i]);
           //cout<<"t  "<<t<<endl;
           int Ans=maxmach();
           //printf("%d\n",Ans);
           if(Ans==n) printf("Y\n");
           else printf("N\n");
        }
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/MeowMeowMeow/p/7334410.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值