(File IO): input:evolution.in output:evolution.out
时间限制: 1000 ms 空间限制: 262144 KB 具体限制
Goto ProblemSet
题目描述
现在是
3019
3019
3019年,在过去的一千年里发生了不计其数的牛类进化,产生了具有各种有趣特性的奶牛。
牛类进化的记录可以用一棵树来表示,起源是位于树根位置的没有特殊特性的奶牛。树上每一个产生后代的结点,有可能所有的奶牛都进化出了一种新的特性(比如说喷火(
f
i
r
e
b
r
e
a
t
h
i
n
g
fire breathing
firebreathing),如下图所示,其中所有斑点(
s
p
o
t
s
spots
spots)奶牛最后都能喷火),或者是奶牛种群产生了分支进化,其中有些进化出了新的特性(比如,飞(
f
l
y
i
n
g
flying
flying)),有的没有。
树底部的叶结点表示
3019
3019
3019年所有产生的奶牛的子种群。没有不同的叶结点(子种群)具有完全相同的一组特性。例如,子种群#1是没有特殊特性的奶牛,子种群#3是能够心灵感应的(
t
e
l
e
p
a
t
h
i
c
telepathic
telepathic)并且会飞的奶牛。相比之下,子种群#2是会飞但不能心灵感应的奶牛。子种群#3是唯一既会飞又会心灵感应的。
像上图这样每一种进化出的新特性都恰好在树中的一条边上产生(也就是说,在整个进化历史中仅在一个时间点产生),这样的进化树被称为是“合法的”。例如,如果斑点这一特性在两个不同分支中均进化产生,这棵进化树就不是合法的。给定
3019
3019
3019年奶牛子种群的描述,请判断是否这可以由一棵合法的进化树所解释。
输入
输入的第一行包含子种群的数量
N
(
2
≤
N
≤
25
)
N(2≤N≤25)
N(2≤N≤25)。以下N行每行描述一个子种群。每行包含一个整数
K
(
0
≤
K
≤
25
)
K(0≤K≤25)
K(0≤K≤25),之后是K个该子种群奶牛所拥有的特性。特性是由至多
20
20
20个小写字母
(
a
.
.
z
)
(a..z)
(a..z)组成的字符串。没有两个子种群拥有完全相同的特性。
输出
如果可能构造一棵可以解释所有子种群产生途径的进化树,输出
"
y
e
s
"
"yes"
"yes",否则输出
"
n
o
"
"no"
"no"。
样例输入
4
2 spots firebreathing
0
1 flying
2 telepathic flying
样例输出
yes
数据范围限制
解题思路
首先感谢
H
J
H~J
H J巨老的详细讲解,我才
A
C
AC
AC了这题。。
对于一个子树
T
T
T,我们设他的儿子为
T
i
T_i
Ti,那么有
T
i
T_i
Ti继承
T
i
−
1
T
r
o
o
t
T_i-1 ~ T_root
Ti−1 Troot. 当一个子节点已经具备属性
a
a
a时,它不可剥离
a
a
a属性,也就是它的儿子的继承集合永远是
[
.
.
.
,
a
,
.
.
.
.
]
[..., a , ....]
[...,a,....],不可能再单独出现属性
b
b
b,而当有一个子节点同时继承了
a
a
a属性与
b
b
b属性,也就是他的继承中有子集
[
a
,
b
]
[a,b]
[a,b],那么他的祖先要么继承
a
a
a要么继承
b
b
b,然后经过一条带有特性
b
b
b或特性
a
a
a的边连接。即若同时出现了一个节点连接
a
a
a,一个节点连接
b
b
b,一个节点只连接
a
、
b
a、b
a、b,那么必然会出现两条a或两条
b
b
b,不符合要求。
- 例:
就比如说子节点 1 1 1继承了 [ a ] [a] [a],子节点 2 2 2继承了 [ b ] [b] [b],子节点 3 3 3继承了 [ a , b ] [a,b] [a,b]。
那么子节点 3 3 3若是子节点 1 1 1的儿子,那么他们俩之间是连接了一条 b b b特性的边,即 子节点1 [ a ] + b — — > [a] + b ——> [a]+b——>子节点3 [ a , b ] [a,b] [a,b]。
而节点2 [ b ] [b] [b]此时不可能由子节点1得来,更不可能从子节点3得来,
s o so so,那么子节点 2 2 2就只能从根节点得来,他们之间需要连接一条特性b的边。即 r o o t [ ] + b — — > root[]+ b ——> root[]+b——> 子节点2 [ b ] [b] [b]
s o so so这样就有两条特性b的边,违背题目条件,无法构造一棵可以解释所有子种群产生途径的进化树了。
同理,若子节点 3 3 3若是子节点 2 2 2的儿子,也无法构造一棵可以解释所有子种群产生途径的进化树。
代码
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<cmath>
#include<set>
using namespace std;
int n;
string s1,s2;
bool A_B , A ,B;
set<string> h[30];
set<string> S;
int main()
{
freopen("evolution.in","r",stdin);
freopen("evolution.out","w",stdout);
scanf("%d",&n);
string s;
int m;
for (int i = 1; i <= n; i++)
{
cin>>m;
for (int j = 1; j <= m; j++)
{
cin >> s;
h[i].insert(s);
S.insert(s);
}
}
for (set<string>::iterator i = S.begin(); i != S.end(); i++)
{
for (set<string>::iterator j = i; j != S.end(); j++)
{
A_B = false , A = false , B = false;
if (*i == *j)
continue;
s1 = *i;
s2 = *j;
for (int k = 1; k <= n; k++)
{
if (h[k].count(s1)&&h[k].count(s2))
{
A_B = true;
continue;
}
if (h[k].count(s1))
{
A = true;
continue;
}
if (h[k].count(s2))
B = true;
}
if (A_B&&A&& B)
{
cout<< "no" <<endl;
return 0;
}
}
}
cout << "yes" << endl;
return 0;
}