注意到若存在两个人同时满足条件的话会推出矛盾,因此满足条件的只能有一个人。开始想到先利用被爱关系,把肯定不满足条件的人踢掉。若果剩下一个人,则判断他是否爱所有人,只见时间一直从0飙到16秒。其实是有线性的方法的,先假定第一个人a满足条件,从第二个人开始遍历。若b爱a或a不爱b,则把a置成b。被覆盖的那些肯定是不满足的条件的,而对于跳过的人,必定存在一个他不爱的人,这就是当时的a,不然,a就要等于他。所以最后对a进行判断即可,包括爱与被爱的关系。
虽然这样做了还是挺玄的,还三秒就超时了,可能是make_pair用多了吧。
#include <cstdio>
#include <map>
#include <set>
#include <string>
#include <memory.h>
using namespace std;
map<string, int> num;
map<string, int>::iterator it;
set< pair<int, int> > r;
int n, m, q, cnt;
int p[60000], top;
string name[60000];
inline int match(char * s)
{
name[cnt] = s;
it = num.find(name[cnt]);
if(it != num.end())
return it->second;
else
return (num[name[cnt]] = cnt++);
}
int main()
{
int T, a, b;
int i, j ,k;
char buf[25];
scanf("%d", &T);
while(T --)
{
scanf("%d%d%d", &n, &m, &q);
cnt = 0, n += m;
num.clear(), r.clear();
for(i=0; i<n; ++i)
{
scanf("%s", buf);
a = match(buf);
scanf("%d", &m);
for(j=0; j<m; ++j)
{
scanf("%s", buf);
b = match(buf);
r.insert(make_pair(a, b));
}
}
for(i=0; i<q; ++i)
{
scanf("%d", &m);
for(j=0; j<m; ++j)
{
scanf("%s", buf);
p[j] = match(buf);
}
for(a=0, j=1; j<m; ++j)
{
if( r.find(make_pair(p[a], p[j]))==r.end() ||
r.find(make_pair(p[j], p[a]))!=r.end() )
a = j;
}
for(k=0; k<m; ++k)
{
if(k == a) continue;
if( r.find(make_pair(p[a], p[k]))==r.end() ||
r.find(make_pair(p[k], p[a]))!=r.end() )
break;
}
if(k < m)
{
printf("0\n");
continue;
}
else
printf("1 %s\n", name[p[a]].c_str());
}
printf("\n");
}
return 0;
}