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:
|
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; }