天梯賽補題 - 家譜處理

這題之前數據結構作業做過,寫的好像挺麻煩的,比賽時也沒功夫寫,今天靜下心來倒是想了個不錯的方法,無BUG 1A

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <set>
#include <vector>
#include <map>
#include <sstream>
#define LL long long
const LL INF = 0x3f3f3f3f;
const int maxn = 200000 + 5;
using namespace std;
int fa[maxn];
int a[maxn];
map<string,int> maps;
string s;
vector<int> vec[maxn];
bool dfs(int f, int son){
    if(vec[f].size() == 0)
        return false;
    for(int i=0; i<vec[f].size(); i++){
        if(vec[f][i] == son) return true;
        if(dfs(vec[f][i],son)) return true;
    }
    return false;
}
bool solve(string name1, string name2, string op){
    int id1 = maps[name1];
    int id2 = maps[name2];
    if(op == "child")
        return fa[id1] == id2;
    if(op == "ancestor")
        return dfs(id1,id2);
    if(op == "sibling")
        return fa[id1] == fa[id2];
    if(op == "parent")
        return fa[id2] == id1;
    if(op == "descendant")
        return dfs(id2,id1);
    return false;
}
int main(){
    int cnt = 0, deep, j;
    int n,q;
    string name;
    cin >> n >> q;
    getchar();
    for(int i=0; i<n; i++){
        deep = 0;
        getline(cin,s);
        int len = (int)s.length();
        for(j=0; j<len; j++){
            if(s[j] == ' ') deep++;
            else break;
        }
        name = s.substr(j,len-j);
        maps[name] = cnt++;
        int id = maps[name];//該串的序號
        deep /= 2;
        int turn = a[deep];//此時的父親
        if(id != 0){
            vec[turn].push_back(id);
            fa[id] = turn;
        }
        else fa[id] = -1;
        a[deep+1] = id;//更新當前層數的父親
    }
    string x;
    while(q--){
        string name1, name2, judge, temp;
        cin >> name1 >> temp >> temp >> judge >> temp >> name2;
        if(solve(name1,name2,judge)) cout << "True" << endl;
        else cout << "False" << endl;
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章