题目:
Two familiar concepts in object oriented programming are the is-a and has-a relationships. Given two classes A and B, we say that A is-a B if A is a subclass of B; we say A has-a B if one of the fields of A is of type B. For example, we could imagine an object-oriented language (call it ICPC++) with code like that in Figure E.1, where the class
D
a
y
Day
Day is-a
T
i
m
e
Time
Time, the class
A
p
p
o
i
n
t
m
e
n
t
Appointment
Appointment is both a
D
a
t
e
B
o
o
k
DateBook
DateBook and a
R
e
m
i
n
d
e
r
Reminder
Reminder, and class
A
p
p
o
i
n
t
m
e
n
t
Appointment
Appointment has-a
D
a
y
Day
Day.
These two relationships are transitive. For example if A is-a B and B is-a C then it follows that A is-a C. This holds as well if we change all the is-a’s in the last sentence to has-a’s. It also works with combinations of is-a’s and has-a’s: in the example above,
A
p
p
o
i
n
t
m
e
n
t
Appointment
Appointment has-a
T
i
m
e
Time
Time, since it has-a
D
a
y
Day
Day and
D
a
y
Day
Day is-a
T
i
m
e
Time
Time. Similarly, if class
D
a
t
e
B
o
o
k
DateBook
DateBook has-a
Y
e
a
r
Year
Year then
A
p
p
o
i
n
t
m
e
n
t
Appointment
Appointment has-a
Y
e
a
r
Year
Year, since
A
p
p
o
i
n
t
m
e
n
t
Appointment
Appointment is-a
D
a
t
e
B
o
o
k
DateBook
DateBook.
In this problem you will be given a set of is-a and has-a relationships and a set of queries of the form
A
A
A is/has-a
B
B
B. You must determine if each query is true or false.
1
≤
n
,
m
≤
10000
1\leq n,m \leq 10000
1≤n,m≤10000,最多
500
500
500 个名称。
分析:
一开始想到的是建一个图,然后按照关系建了两种边,然后用
d
f
s
dfs
dfs 判断询问的两点中,一个点能不能到达另一个点。但这样的话边的情况会复杂,容易出错。求两点之间的可达关系,直接求传递闭包即可,更新条件见代码。
复杂度:
O
(
50
0
3
)
O(500^3)
O(5003)
#include <bits/stdc++.h>
using namespace std;
const int N=510;
bool pa[N][N],pb[N][N];
map<string,int>mp;
int cnt;
void solve()
{
for(int k=1;k<=cnt;k++)
{
pa[k][k]=1;
for(int i=1;i<=cnt;i++)
{
for(int j=1;j<=cnt;j++)
{
if(pa[i][k]&&pa[k][j])
pa[i][j]=1;
if(pa[i][k]&&pb[k][j]||pb[i][k]&&pa[k][j]||pb[i][k]&&pb[k][j])
pb[i][j]=1;
}
}
}
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
string a,r,b;
cnt=0;
for(int i=1;i<=n;i++)
{
cin>>a>>r>>b;
if(mp[a]==0)
mp[a]=++cnt;
if(mp[b]==0)
mp[b]=++cnt;
if(r.compare("is-a")==0)
pa[mp[b]][mp[a]]=1;
else
pb[mp[b]][mp[a]]=1;
}
solve();
for(int i=1;i<=m;i++)
{
printf("Query %d: ",i);
cin>>a>>r>>b;
if(r.compare("is-a")==0)
{
if(pa[mp[b]][mp[a]])
printf("true\n");
else
printf("false\n");
}
else
{
if(pb[mp[b]][mp[a]])
printf("true\n");
else
printf("false\n");
}
}
return 0;
}