题目描述:高级语言中类有 is-a 和 has-a 的概念(balabala)
题目链接:https://codeforces.com/gym/101673
(训练时最后一小时一顿盲目分析判断要缩点然后求LCA,开始动手写发现has-a的关系不好写。敲了快一个小时之后发现点数不超过500个,已来不及重写)
题解:点数较小的图可以直接用floyd求传递闭包,对于is-a的关系,直接传递is-a的关系即可。
对于has-a的关系,有三种关系可以传递has-a的关系,求has-a关系之前先求出is-a关系的闭包。
(读题有多重要,血的教训)
代码
#include<bits/stdc++.h>
using namespace std;
int n,m;
const int maxn = 1e3 + 10;
map<string,int> mp;
char a[maxn],b[maxn],c[maxn];
int has[maxn][maxn];
int is[maxn][maxn];
int main() {
scanf("%d%d",&n,&m);
int tot = 0;
for(int i = 1; i <= n; i++) {
scanf("%s%s%s",a,b,c);
if(!mp[a]) mp[a] = ++tot;
if(!mp[c]) mp[c] = ++tot;
if(b[0] == 'i') is[mp[a]][mp[c]] = 1;
if(b[0] == 'h') has[mp[a]][mp[c]] = 1;
}
for(int i = 1; i <= tot; i++)
is[i][i] = 1;
for(int k = 1; k <= tot; k++)
for(int i = 1; i <= tot; i++)
for(int j = 1; j <= tot; j++) {
if(is[i][k] && is[k][j])
is[i][j] = 1;
}
for(int k = 1; k <= tot; k++)
for(int i = 1; i <= tot; i++)
for(int j = 1; j <= tot; j++) {
if(has[i][k] && has[k][j])
has[i][j] = 1;
if(is[i][k] && has[k][j])
has[i][j] = 1;
if(has[i][k] && is[k][j])
has[i][j] = 1;
}
for(int i = 1; i <= m; i++) {
scanf("%s%s%s",a,b,c);
if(!mp[a]) mp[a] = ++tot;
if(!mp[c]) mp[c] = ++tot;
if(b[0] == 'i') {
if(is[mp[a]][mp[c]]) printf("Query %d: true\n",i);
else printf("Query %d: false\n",i);
}
if(b[0] == 'h') {
if(has[mp[a]][mp[c]]) printf("Query %d: true\n",i);
else printf("Query %d: false\n",i);
}
}
}