ICPC North Central NA Contest 2017 - Is-A? Has-A? Who Knowz-A? (Floyd求传递闭包)

题目链接

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.1E.1, where the class DayDay is-a TimeTime, the class AppointmentAppointment is both a DateBookDateBook and ReminderReminder, and class AppointmentAppointment has-a DayDay.
在这里插入图片描述
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, AppointmentAppointment has-a TimeTime, since it has-a DayDay and DayDay is-a TimeTime. Similarly, if class DateBookDateBook has-a YearYear then AppointmentAppointment has-a YearYear, since AppointmentAppointment is-a DateBookDateBook.In this problem you will be given a set of is-a and has-a relationships and a set of queries of the form AA is/has-a BB. You must determine if each query is true or false.

Input
Input starts with two integers nn and mm, (1≤n,m≤10000)(1≤n,m≤10000), where nn specifies the number of given is-a and has-a relationships and mm specifies the number of queries. The next nn lines each contain one given relationship in the form are single-word class names, and rr is either the string “is-a” or “has-a”. Following this are mm queries, one per line, using the same format. There will be at most 500500 distinct class names in the n+mn+m lines, and all class names in the last mm lines will appear at least once in the initial nn lines. All is-a and has-a relationships between the given classes can be deduced from the nn given relationships. Is-a relationships can not be circular (apart from the trivial identity “xx is-a xx”).

Output
For each query, display the query number (starting at one) and whether the query is true or false.

1.题目大意:给出面向对象的一些概念,如"A is-a B"代表A是B的子类。然后还有一个"A has-a B"代表A类下有B类的定义。先给出若干这些关系式,然后给出m个表达式判断是对还是错

2.这道题很遗憾差一点就做出来了,因为有一句话的意思理解错了。当我吃完饭再读题时发现了自己的错误,然后写了1A了。之前做过Floyd求传递闭包,这个很相似,无非就是由一些已知的直接联系的关系去求判断一些关系式是否对错。那么我们来分析一下这一道题,可以看出来"is-a"即子类的关系是很好判断的,就像大小关系一样,A是B的子类就代表B比A大,那么再由一些其他的相关的大小关系很容易去判断。显然如果存在关系我们设两点之间存在一条有向边由A指向B,那么经过Floyd对所有边的“松弛”,就能得到子类关系的判断(这里的松弛是指如果存在i指向k,k又指向j,那么i就指向j)

3.但是"has-a"关系怎么判断,其实类似,但是题目都给我们说明白了: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, Appointment has-a Time, since it has-a Day and Day is-a Time. Similarly, if class DateBook has-a Year then Appointment has-a Year, since Appointment is-a DateBook. 仔细读这句话,我们发现如果在得出所有的"is-a"关系的判断后,那么就直接按上面这三个条件“松弛”另外一个图的边即可(比赛时把最后一个since翻译成了结果,但是实际上是条件)

代码

#include <iostream>
#include <cstring>
#include <algorithm>
#include <tr1/unordered_map>
using namespace std;
#define INF 0x3f3f3f3f
tr1::unordered_map<string,int> mp;
int n,m,num;
string a,b,c;
int is[505][505],has[505][505];

void getID(string s){  //字符串ID化
    if(!mp.count(s)){
        mp[s]=++num;
    }
}

void Floyd1(){
    for(int k=1;k<=502;k++)
    for(int i=1;i<=502;i++)
    for(int j=1;j<=502;j++){
        if(is[i][k] && is[k][j])
            is[i][j]=1;
    }
}

void Floyd2(){
    for(int k=1;k<=502;k++)
    for(int i=1;i<=502;i++)
    for(int j=1;j<=502;j++){
        if(has[i][k] && has[k][j]){
            has[i][j]=1;
        }else if(has[i][k] && is[k][j]){
            has[i][j]=1;
        }else if(is[i][k] && has[k][j]){
            has[i][j]=1;
        }
    }
}

int main()
{
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin>>n>>m;
    num=0;
    memset(is,0,sizeof is);
    memset(has,0,sizeof has);
    for(int i=1;i<=n;i++){
        cin>>a>>b>>c;
        getID(a),getID(c);
        if(b[0]=='i'){
            is[mp[a]][mp[c]]=1;
        }else if(b[0]=='h'){
            has[mp[a]][mp[c]]=1;
        }
    }
    Floyd1();
    Floyd2();
    for(int i=1;i<=502;i++){  //注意只说了可以把自己作为子类,另外一个没有说,请仔细读题
        is[i][i]=1;
    }
    int kase=1;
    for(int i=1;i<=m;i++){
        cin>>a>>b>>c;
        if(b[0]=='i'){
            cout<<"Query "<<kase++<<": "<<(is[mp[a]][mp[c]]==0?"false\n":"true\n");
        }else if(b[0]=='h'){
            cout<<"Query "<<kase++<<": "<<(has[mp[a]][mp[c]]==0?"false\n":"true\n");
        }
    }
    return 0;
}

发布了128 篇原创文章 · 获赞 7 · 访问量 5267

猜你喜欢

转载自blog.csdn.net/qq_44691917/article/details/104583850