2020寒假【gmoj2409】【Cow Evolution】

题目描述

现在是3019年,在过去的一千年里发生了不计其数的牛类进化,产生了具有各种有趣特性的奶牛。
牛类进化的记录可以用一棵树来表示,起源是位于树根位置的没有特殊特性的奶牛。树上每一个产生后代的结点,有可能所有的奶牛都进化出了一种新的特性(比如说喷火(fire breathing),如下图所示,其中所有斑点(spots)奶牛最后都能喷火),或者是奶牛种群产生了分支进化,其中有些进化出了新的特性(比如,飞(flying)),有的没有。
在这里插入图片描述
树底部的叶结点表示3019年所有产生的奶牛的子种群。没有不同的叶结点(子种群)具有完全相同的一组特性。例如,子种群#1是没有特殊特性的奶牛,子种群#3是能够心灵感应的(telepathic)并且会飞的奶牛。相比之下,子种群#2是会飞但不能心灵感应的奶牛。子种群#3是唯一既会飞又会心灵感应的。
像上图这样每一种进化出的新特性都恰好在树中的一条边上产生(也就是说,在整个进化历史中仅在一个时间点产生),这样的进化树被称为是“合法的”。例如,如果斑点这一特性在两个不同分支中均进化产生,这棵进化树就不是合法的。给定3019年奶牛子种群的描述,请判断是否这可以由一棵合法的进化树所解释。

输入

输入的第一行包含子种群的数量N(2≤N≤25)。以下N行每行描述一个子种群。每行包含一个整数K(0≤K≤25),之后是K个该子种群奶牛所拥有的特性。特性是由至多20个小写字母(a…z)组成的字符串。没有两个子种群拥有完全相同的特性。

输出

如果可能构造一棵可以解释所有子种群产生途径的进化树,输出"yes",否则输出"no"。

样例输入

4
2 spots firebreathing
0
1 flying
2 telepathic flying

样例输出

yes

分析

巧妙的暴力
设a为一个家族,b为另一个家族
情况1:a的能力包含b的能力
情况2:a和b的能力一样
情况3:a和b有不同的能力
情况4:a和b有的能力相同,有的能力不同,输出−1 。

上代码

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
string s[100][100],a[100];
int n,ff[100],w,c,t,tj;
string str;
int pd(string a,string b)
{
	int f1=0,f2=0,s1=0,s2=0,v=0;
	for(int i=1;i<=n;i++)    //枚举a和b
	{
		f1=0,f2=0;
		for(int j=1;j<=ff[i];j++)
		{
			if(s[i][j]==a) f1=1;
			if(s[i][j]==b) f2=1;
		}
		if(f1!=0&&f2==0) s1=1;
		if(f2!=0&&f1==0) s2=1;
		if(f1!=0&&f2!=0) v=1;
	}
	return s1>0&&s2>0&&v>0;
}
int main()
{
	freopen("evolution.in","r",stdin);
	freopen("evolution.out","w",stdout);
	cin>>n;
	for(int i=1; i<=n; i++)
	{
	 	tj=0;
		cin>>t;
		ff[i]=t;
		for(int j=1; j<=t; j++)    //直接储存字符串
		{
			cin>>str;
			tj++,w=0,s[i][tj]=str;
			for(int k=1; k<=c; k++)
			{
				if(a[k]==str)
				{
					w=1;
					break;
				}
			}
			if(w==0)
			{
				c++;
				a[c]=str; //如果没有相同的,就新创一个格子
			} 
		}
	}
	for(int i=1;i<=c;i++)
	{
		for(int j=i+1;j<=c;j++)
		{
			if(pd(a[i],a[j])!=0) 
	       {
				cout<<"no";
				return 0;
	       }
		}
	}
	cout<<"yes";
	return 0;
}

发布了110 篇原创文章 · 获赞 100 · 访问量 8003

猜你喜欢

转载自blog.csdn.net/dglyr/article/details/105300003