并查集 xtu-2170 ACM ICPC 2011–2012, Northeastern European Regional Contest Problem E. Eve

此题看似繁冗,其实是水题,只要并查集就可解决。

 注意信息的汲取……

ACM ICPC 2011–2012, Northeastern European Regional Contest
St. Petersburg – Barnaul – Tashkent – Tbilisi, November 27, 2011
Problem E. Eve
Input file: eve.in
Output file: eve.out
Mitochondrial DNA is the Deoxyribonucleic acid molecule that is contained in mitochondria within cells
of an organism.
Mitochondrial DNA is normally passed to a child exclusively from its mother. Because of this fact, it is
possible to speak of “Mitochondrial Eve” which refers to the most recent common matrilineal ancestor
of the entire population. Matrilineal ancestry is traced through female line: mother, grandmother, etc.
Mitochondrial Eve of the Earth’s human population is estimated to have lived around 200 000 years ago,
most likely in the East Africa.
In this problem, we consider a certain population of the same biological species (eukaryotic and anisogamous).
The population has been observed for a period of time, and all births and deaths were clearly
recorded. For some of the individuals within the population, their mitochondrial DNA was sequenced.
It is assumed that each individual in the observed population received its mitochondrial DNA from its
mother without any mutations.
Your task is to find out, whether all individuals currently alive have the same mitochondrial DNA.
Input
The first line of the input file contains integer n (1 ≤ n ≤ 100 000), the number of individuals that were
alive at the beginning of the observation period. IDs of these individuals are integers from 1 to n.
Next n lines contain one character each. The i-th of these lines describes the sex of the individual with
ID i. ‘M’ stands for male, ‘F’ stands for female.
The next line contains integer m (0 ≤ m ≤ 100 000), the total number of births and deaths that happened
during the observation period.
Next m lines contain description of birth and death events, listed in chronological order.
A birth event is described by three space-separated tokens: the ID of the father, the ID of the mother,
and a character that describes the sex of the child (‘M’ for male, ‘F’ for female). The ID given to the
offspring is the smallest positive integer that hasn’t been used as an ID by this point of time.
A death event is described by a single negative integer, whose absolute value equals the ID of the individual
that died.
The next line contains integer k (0 ≤ k ≤ n + m), the number of sequenced mitochondrial DNAs.
Each of the next k lines contains two space-separated integers, the ID of the individual whose mitochondrial
DNA has been sequenced, and the unique identifier of the mitochondrial DNA of that individual.
Unique identifiers of two mitochondrial DNAs are the same if and only if the corresponding sequenced
mitochondrial DNAs are the same. All unique identifiers of the mitochondrial DNAs are integers from 1
to 109.
All the data given in the input file is consistent and non-contradictory. Each individual’s mitochondrial
DNA was sequenced at most once. At least one individual was alive at the end of the observation period.
Output
The output file must contain a single word:
• YES – if it can be derived that all the individuals that are alive at the end of the experiment have
the same mitochondrial DNA;
• NO – if it can be derived that some of the individuals that are alive at the end of the experiment
have different mitochondrial DNA;
• POSSIBLY – if none of the cases above takes place.
Page 6 of 16
ACM ICPC 2011–2012, Northeastern European Regional Contest
St. Petersburg – Barnaul – Tashkent – Tbilisi, November 27, 2011
Sample input and output
eve.in eve.out
4
M
F
M
F
12
3 4 F
1 2 M
1 2 M
3 4 F
-3
-2
-4
-1
6 5 M
7 5 F
-7
-6
0
YES
3
F
F
M
3
3 2 M
3 1 F
-3
2
4 100500
5 100500
YES
3
M
F
M
2
1 2 M
3 2 F
0
POSSIBLY
2
M
F
2
1 2 M
-2
2
1 2011
2 2012
NO

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#define MAXINT 0x7fffffff
#define N 200009
using namespace std;

struct HIN{
       char sex;
       int dna,lif,mot;
}hin[N];

int find_mot(int x){return hin[x].mot==-x ? x: hin[x].mot=find_mot(hin[x].mot);}

int eve(int *pn){
     int i,m,tm,tf;
     scanf("%d",&m);
     for(i=1;i<=m;i++){
         scanf("%d",&tf);
         if(tf>0){//大于零,表出生
            scanf("%d",&tm);
            getchar();
            hin[++(*pn)].sex=getchar();
            hin[*pn].mot=tm;//题目已告知后者为其母
            hin[*pn].lif=1;
         }
         else hin[-tf].lif=0;//小于零,则死亡
     }
     return m;
}

void getdna(){
     int k,id,dna;
     scanf("%d",&k);
     while(k--){
           scanf("%d %d",&id,&dna);
           hin[find_mot(id)].dna=dna;
     }
}

void query(int n,int m){
     int i,tp,tn,np=0,nn=0,flan=1,flap=1;
     for(i=1;i<=n;i++)
         if(hin[i].lif){
            if(hin[find_mot(i)].dna>0){//DNA大于零表给定已知的DNA,
               if(flap){//第一次记录
                  flap=0;
                  tp=i;
                  np++;
               }
               else if(hin[find_mot(i)].dna!=hin[find_mot(tp)].dna){//判断是否存在已知不同DNA
                      printf("NO\n");
                      return;
               }
            }
            else{
                 if(flan){
                    flan=0;
                    tn=i;
                    nn++;
                 }
                 else if(hin[find_mot(i)].dna!=hin[find_mot(tn)].dna) nn++;//记录未知dna数量
            }
        }
     if(nn>1||(np&&nn)) printf("POSSIBLY\n");//至少有两种DNA,则为未知
     else printf("YES\n");
}

int main(){
    int n,m,i,j;
    char c;
    while(scanf("%d",&n)==1){
          getchar();
          for(i=1;i<=n;i++){
              c=getchar();
              hin[i].sex=c;
              hin[i].dna=-i;
              hin[i].mot=-i;
              hin[i].lif=1;
              getchar();
          }
          m=eve(&n);//发生了事件
          /*for(i=1;i<=n;i++)这里可以先不用并查……
              j=find_mot(i);*/
          getdna();//输入DNA
          query(n,m);//检查最终存活者DNA同异情况
    }
    return 0;
}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值