Problem:
カツサンド (Cutlet Sandwich)

ある世界には、 $X$ 種類の「サンド」、 $Y$ 種類の「カツ」、 $Z$ 種類の「カレー」という食べ物があります。

この世界には $N$ 種類の「カツサンド」という食べ物があり、 $i$ 種類目のカツサンドは $A_i$ 種類目のサンドと $B_i$ 種類目のカツが原料です。

また、 $M$ 種類の「カツカレー」という食べ物があり、 $i$ 種類目のカツカレーは $C_i$ 種類目のカツと $D_i$ 種類目のカレーが原料です。

Segtree 君は、あるカツサンドまたはカツカレーを持っているとき、原料のうち少なくとも $1$ つが共通しているようなカツサンドまたはカツカレーと交換することができます。

例えば、$a$ 種類目のサンドと $b$ 種類目のカツが原料であるカツサンドを持っているとき、 $a$ 種類目のサンドまたは $b$ 種類目のカツを原料に持つ任意のカツサンド、または、 $b$ 種類目のカツを原料に含む任意のカツカレーと交換できます。

今、 Segtree 君は $S$ 種類目のカツサンドを持っていますが、食べたいのは $T$ 種類目のカツカレーです。

$T$ 種類目のカツカレーを手に入れることができるか判定してください。もし可能ならば、最小何回の交換で目的のカツカレーを手にいられるかを求めてください。

入力

入力は以下の形式で標準入力から与えられる。

$X$ $Y$ $Z$ $N$ $M$ $S$ $T$
$A_1$ $B_1$
$A_2$ $B_2$
$\ldots$
$A_N$ $B_N$
$C_1$ $D_1$
$C_2$ $D_2$
$\ldots$
$C_M$ $D_M$

出力

$T$ 種類目のカツカレーを手に入れるために必要な最小の交換回数を出力してください。手に入れることが不可能ならば、代わりに「 $-1$ 」を出力してください。

ただし、最後には改行を入れること。

制約

$1 \leq X,Y,Z,N,M \leq 10^5$

$1 \leq S \leq N$

$1 \leq T \leq M$

$1 \leq A_i \leq X$

$1 \leq B_i \leq Y$

$1 \leq C_i \leq Y$

$1 \leq D_i \leq Z$

入力は全て整数である。

入力例1

1 1 1 1 1 1 1
1 1
1 1

出力例1

1

入力例2

2 3 4 3 5 1 5
1 1
1 2
2 2
2 1
3 1
3 2
3 3
3 4

出力例2

4

入力例3

1 2 2 1 2 1 1
1 2
1 2
2 1

出力例3

-1

Solution in Rust (judge verdict: Accepted)

//https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8 より
macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
    ($($r:tt)*) => {
        let s = {
            use std::io::Read;
            let mut s = String::new();
            std::io::stdin().read_to_string(&mut s).unwrap();
            s
        };
        let mut iter = s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
}

macro_rules! input_inner {
    ($iter:expr) => {};
    ($iter:expr, ) => {};
    ($iter:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($iter, $t);
        input_inner!{$iter $($r)*}
    };
}

macro_rules! read_value {
    ($iter:expr, ( $($t:tt),* )) => {
        ( $(read_value!($iter, $t)),* )
    };
    ($iter:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
    };
    ($iter:expr, chars) => {
        read_value!($iter, String).chars().collect::<Vec<char>>()
    };
    ($iter:expr, usize1) => {
        read_value!($iter, usize) - 1
    };
    ($iter:expr, $t:ty) => {
        $iter.next().unwrap().parse::<$t>().expect("Parse error")
    };
}

//

fn run() {
    input! {
        x: usize,
        y: usize,
        z: usize,
        n: usize,
        m: usize,
        src: usize1,
        dst: usize1,
        a: [(usize1, usize1); n],
        b: [(usize1, usize1); m],
    }
    let mut g = vec![vec![]; n + m + x + y + z];
    let dst = n + dst;
    for (i, &(a, b)) in a.iter().enumerate() {
        let a = a + n + m;
        let b = b + n + m + x;
        g[i].push((a, 1));
        g[i].push((b, 1));
        g[a].push((i, 0));
        g[b].push((i, 0));
    }
    for (j, &(c, d)) in b.iter().enumerate() {
        let j = n + j;
        let c = c + n + m + x;
        let d = d + n + m + x + y;
        g[j].push((c, 1));
        g[j].push((d, 1));
        g[c].push((j, 0));
        g[d].push((j, 0));
    }
    let mut dp = vec![std::u32::MAX; n + m + x + y + z];
    dp[src] = 0;
    let mut deq = std::collections::VecDeque::new();
    deq.push_back(src);
    while let Some(v) = deq.pop_front() {
        let d = dp[v];
        for &(u, c) in g[v].iter() {
            if dp[u] > d + c {
                dp[u] = d + c;
                if c == 0 {
                    deq.push_front(u);
                } else {
                    deq.push_back(u);
                }
            }
        }
    }
    let ans = dp[dst];
    if ans == std::u32::MAX {
        println!("-1");
    } else {
        println!("{}", ans);
    }
}

fn main() {
    run();
}