use std::collections::hash_set::Iter;
use std::rc::Rc;
use std::ops::DivAssign;
use std::ops::MulAssign;
use std::ops::SubAssign;
use std::collections::BinaryHeap;
use std::str::FromStr;
use std::collections::HashSet;
use std::collections::BTreeMap;
use std::fmt::Display;
use std::ops::Neg;
use std::ops::Div;
use std::ops::Mul;
use std::ops::Add;
use std::ops::{AddAssign, Sub};
use std::cmp::max;
use std::collections::VecDeque;
use std::cmp::min;
use std::collections::{HashMap, BTreeSet};
use std::cmp::Ordering;
use std::fmt::Debug;

fn read_line() -> String {
    let mut buffer = String::new();
    std::io::stdin().read_line(&mut buffer).expect("No Line");
    buffer.trim().to_owned()
}
fn read_lines<T: std::str::FromStr>(count: usize) -> Vec<T> {
    let mut buffer = String::new();
    let mut vec = Vec::with_capacity(count);
    for _ in 0 .. count {
        std::io::stdin().read_line(&mut buffer).expect("No Line");
        vec.push(buffer.trim().parse().ok().expect("Can't Parse"));
        buffer.clear();
    }
    vec
}
fn read_tabulate<R, T: Fn(&str)->R> (count: usize, transformer: T) -> Vec<R> {
    let mut buffer = String::new();
    let mut vec = Vec::with_capacity(count);
    for _ in 0 .. count {
        std::io::stdin().read_line(&mut buffer).expect("No Line");
        vec.push(transformer(buffer.trim()));
        buffer.clear();
    }
    vec
}
fn read_value<T: std::str::FromStr>() -> T {
    read_line().trim().parse().ok().unwrap()
}
fn read_values<T: std::str::FromStr>() -> Vec<T> {
    read_line().trim().split_whitespace().map(|x| x.parse().ok().expect("Can't Parse")).collect::<Vec<T>>()
}
macro_rules! freeze {
    ($($id:ident), *) => {
        $(let $id = $id;)*
    };
}
macro_rules! read_map {
    ($ident: ident: [$block: block; $size: expr]) => {
        let $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
    (mut $ident: ident: [$block: block; $size: expr]) => {
        let mut $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
}
macro_rules! read {
    (mut $ident: ident: String) => {
        let mut $ident = read_value::<String>();
    };
    ($ident: ident: String) => {
        let $ident = read_value::<String>();
    };
    (mut $ident: ident: [$ty:ty]) => {
        let mut $ident = read_values::<$ty>();
    };
    ($ident: ident: [$ty:ty]) => {
        let $ident = read_values::<$ty>();
    };
    (mut $ident: ident: [[$ty:ty]; $size: expr]) => {
        let mut $ident = (0 .. $size).into_iter().map(|_| read_values::<$ty>()).collect::<Vec<_>>();
    };
    ($ident: ident: [[$ty:ty]; $size: expr]) => {
        let $ident = (0 .. $size).into_iter().map(|_| read_values::<$ty>()).collect::<Vec<_>>();
    };
    (mut $ident: ident: [$ty:ty; $size:expr]) => {
        let mut $ident = read_lines::<$ty>($size);
    };
    ($ident: ident: [$ty:ty; $size:expr]) => {
        let $ident = read_lines::<$ty>($size);
    };
    ($ident: ident: [$block: block; $size: expr]) => {
        let $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
    (mut $ident: ident: [$block: block; $size: expr]) => {
        let mut $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
    ($($token: tt)*) => {
        let mut iter = read_values::<String>().into_iter();
        read_from_iter!(iter; $($token)*);
    };
}
macro_rules! read_from_iter {
    ($iter:expr; mut $ident:ident:$ty:ty, $($rest:tt)*) => {
        let mut $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
        read_from_iter!($iter; $($rest)*);
    };
    ($iter:expr; $ident:ident:$ty:ty, $($rest:tt)*) => {
        let $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
        read_from_iter!($iter; $($rest)*);
    };
    ($iter:expr; mut $ident:ident:$ty:ty) => {
        let mut $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
    };
    ($iter:expr; $ident:ident:$ty:ty) => {
        let $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
    };
    ($iter: expr; ) => {};
}
struct KeyValue<K, V> {
    key: K,
    value: V
}
impl <K: PartialOrd, V> PartialEq for KeyValue<K, V> {
    fn eq(&self, other: &Self) -> bool {
        self.key.eq(&other.key)
    }
}
impl <K: PartialOrd, V> Eq for KeyValue<K, V> {}
impl <K: PartialOrd, V> PartialOrd for KeyValue<K, V> {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        self.key.partial_cmp(&other.key)
    }
}
impl <K: PartialOrd, V> Ord for KeyValue<K, V> {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.key.partial_cmp(&other.key).ok_or("Can't Compare").unwrap()
    }
}

struct UnionFind {
    vec: Vec<i32>
}
impl UnionFind {
    fn new(size: usize) -> UnionFind {
        UnionFind{vec: vec![-1; size]}
    }
    fn find(&mut self, a: usize) -> usize {
        if self.vec[a] < 0 {
            a
        }else {
            let parent = self.vec[a];
            let root = self.find(parent as usize);
            self.vec[a] = root as i32;
            root
        }
    }
    fn same(&mut self, a: usize, b: usize) -> bool {
        self.find(a) == self.find(b)
    }
    fn unite(&mut self, mut a: usize, mut b: usize) {
        a = self.find(a);
        b = self.find(b);
        if a == b {return ;}
        if self.vec[a] < self.vec[b] {
            self.vec[a] += self.vec[b];
            self.vec[b] = a as i32;
        }else {
            self.vec[b] += self.vec[a];
            self.vec[a] = b as i32;
        }
    }
}
fn main() {
    loop {
        read!(n: usize);
        if n == 0 {break;}
        read_map!(cross: [{
            read!(name: String);
            let names = name.split('-').collect::<Vec<_>>();
            let prior = names[0];
            let sub = names[1];
            (prior.to_owned(), sub.to_owned())
        }; n]);
        let mut roads = HashMap::<String, Vec<HashSet<String>>>::new();
        for t in &cross {
            let p = t.0.to_owned();
            let s = t.1.to_owned();
            roads.entry(p.to_owned()).or_insert(vec![HashSet::new(); 2])[1].insert(s.to_owned());
            roads.entry(s.to_owned()).or_insert(vec![HashSet::new(); 2])[0].insert(p.to_owned());
            //println!("{:?}", roads);
        }
        let names = roads.iter().map(|(s, _)| s).cloned().collect::<Vec<_>>();
        let mut indices = HashMap::<String, usize>::new();
        for i in 0 .. names.len() {
            indices.insert(names[i].to_owned(), i);
        }
        let mut same_level = UnionFind::new(roads.len());
        for i in 0 .. names.len() {
            for j in 0 .. i {
                if roads[&names[i]][0].intersection(&roads[&names[j]][1]).next().is_none() && 
                    roads[&names[j]][0].intersection(&roads[&names[i]][1]).next().is_none() && 
                    !(roads[&names[i]][0].intersection(&roads[&names[j]][0]).next().is_none() &&
                    roads[&names[i]][1].intersection(&roads[&names[j]][1]).next().is_none()) {
                    same_level.unite(i, j);
                }
            }
        }
        for i in 0 .. names.len() {
            let root = same_level.find(i);
            if root == i { continue; }
            let mut relation = roads.get_mut(&names[i]).unwrap().drain(..).collect::<Vec<_>>();
            roads.remove(&names[i]);
            for (j, mut set) in relation.drain(..).enumerate() {
                for name in set.drain() {
                    roads.get_mut(&names[root]).unwrap()[j].insert(name);
                }
            }
        }
        println!("{}", indices.len());
        read!(m: usize);
        for _ in 0 .. m {
            read!(query: String);
            let pair = query.split('-').map(|name| name.to_owned()).filter(|name| indices.contains_key(name)).map(|name| same_level.find(indices[&name])).collect::<Vec<_>>();
            if pair.len() == 2{
                let from = pair[0];
                let to = pair[1];
                let mut depth = vec![-1; indices.len()];
                let mut stack = Vec::new();
                depth[from] = 0;
                stack.push(from);
                while let Some(top) = stack.pop() {
                    if depth[to] >= 0 {break;}
                    for name in & roads[&names[top]][1] {
                        let i = same_level.find(indices[name]);
                        if depth[i] >= 0{continue;}
                        stack.push(i);
                        depth[i] = depth[top] + 1;
                    }
                }
                if depth[to] >= 0 && (depth[from] ^ depth[to]) & 1 == 1 {
                    println!("YES");
                }else {
                    println!("NO");
                }
            }else {
                println!("NO");
            }
        }
    }
}


Measured memory_bytes: 5080