Problem:
Score : 900 points

Problem Statement

You are given an undirected graph consisting of N vertices and M edges.
The vertices are numbered 1 to N, and the edges are numbered 1 to M.
In addition, each vertex has a label, A or B. The label of Vertex i is s_i.
Edge i bidirectionally connects vertex a_i and b_i.

The phantom thief Nusook likes to choose some vertex as the startpoint and traverse an edge zero or more times.
Today, he will make a string after traveling as above, by placing the labels of the visited vertices in the order visited, beginning from the startpoint.

For example, in a graph where Vertex 1 has the label A and Vertex 2 has the label B, if Nusook travels along the path 1 \rightarrow 2 \rightarrow 1 \rightarrow 2 \rightarrow 2, the resulting string is ABABB.

Determine if Nusook can make all strings consisting of A and B.

Constraints

2 \leq N \leq 2 \times 10^{5}

1 \leq M \leq 2 \times 10^{5}

|s| = N

s_i is A or B.

1 \leq a_i, b_i \leq N

The given graph may NOT be simple or connected.

Input

Input is given from Standard Input in the following format:

N M
s
a_1 b_1
:
a_{M} b_{M}

Output

If Nusook can make all strings consisting of A and B, print Yes; otherwise, print No.

Sample Input 1

2 3
AB
1 1
1 2
2 2

Sample Output 1

Yes

Since Nusook can visit Vertex 1 and Vertex 2 in any way he likes, he can make all strings consisting of A and B.

Sample Input 2

4 3
ABAB
1 2
2 3
3 1

Sample Output 2

No

For example, Nusook cannot make BB.

The given graph may not be connected.

Sample Input 3

13 23
ABAAAABBBBAAB
7 1
10 6
1 11
2 10
2 8
2 11
11 12
8 3
7 12
11 2
13 13
11 9
4 1
9 7
9 6
8 13
8 6
4 10
8 7
4 3
2 1
8 12
6 9

Sample Output 3

Yes

Sample Input 4

13 17
BBABBBAABABBA
7 1
7 9
11 12
3 9
11 9
2 1
11 5
12 11
10 8
1 11
1 8
7 7
9 10
8 8
8 12
6 2
13 11

Sample Output 4

No

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

//#define NDEBUG
#include <cstddef>
#include <cstdint>
#include <vector>

using i8 = ::std::int_least8_t;
using i32 = ::std::int_least32_t;
using i64 = ::std::int_least64_t;
using u8 = ::std::uint_least8_t;
using u32 = ::std::uint_least32_t;
using u64 = ::std::uint_least64_t;
using isize = ::std::ptrdiff_t;
using usize = ::std::size_t;

class rep {
	const usize f, l;

public:
	class itr {
		friend rep;
		usize i;
		itr(usize x) noexcept : i(x) {}

	public:
		void operator++() noexcept { ++i; }
		usize operator*() const noexcept { return i; }
		bool operator!=(const itr x) const noexcept { return i != x.i; }
	};
	rep(usize first, usize last) noexcept : f(first), l(last) {}
	itr begin() const noexcept { return itr(f); }
	itr end() const noexcept { return itr(l); }
};
class revrep {
	const usize f, l;

public:
	class itr {
		friend revrep;
		usize i;
		itr(usize x) noexcept : i(x) {}

	public:
		void operator++() noexcept { --i; }
		usize operator*() const noexcept { return i; }
		bool operator!=(const itr x) const noexcept { return i != x.i; }
	};
	revrep(usize first, usize last) noexcept : f(first), l(last) {}
	itr begin() const noexcept { return itr(l - 1); }
	itr end() const noexcept { return itr(f - 1); }
};
template <class T> bool maxi(T &a, const T &b) {
	return a <= b ? (a = b, 1) : 0;
}
template <class T> bool mini(T &a, const T &b) {
	return b <= a ? (a = b, 1) : 0;
}
template <class T> bool smaxi(T &a, const T &b) {
	return b <= a ? 0 : (a = b, 1);
}
template <class T> bool smini(T &a, const T &b) {
	return a <= b ? 0 : (a = b, 1);
}
template <class T> using vec_alias = ::std::vector<T>;
template <class T> auto md_vec(usize n, const T &value) {
	return ::std::vector<T>(n, value);
}
template <class... Args> auto md_vec(usize n, Args... args) {
	return ::std::vector<decltype(md_vec(args...))>(n, md_vec(args...));
}
template <class T> const T &as_const(const T &v) noexcept { return v; }

#include <algorithm>
#include <iostream>
#include <utility>
#include <string>
#include <stack>

int main() {
	u32 n, m;
	::std::string s;
	::std::cin >> n >> m >> s;
	::std::vector<::std::vector<u32>> g(n * 2);
	while (m--) {
		u32 a, b;
		::std::cin >> a >> b;
		--a;--b;
		if (s[a] == s[b]) {
			g[a].emplace_back(b + n);
			g[b].emplace_back(a + n);
		}
		else {
			g[a + n].emplace_back(b);
			g[b + n].emplace_back(a);
		}
	}
	::std::vector<u32> deg(n * 2, 0);
	for (const auto &v:g) {
		for (const auto j : v) {
			++deg[j];
		}
	}
	::std::stack<u32> st;
	for (const auto i : rep(0, n * 2)) {
		if (!deg[i])
			st.push(i);
	}	

	while (!st.empty()) {
		const auto v = st.top();
		st.pop();
		for (const auto u : g[v]) {
			--deg[u];
			if (!deg[u])
				st.push(u);
		}
	}
	for (const auto d : deg) {
		if (d) {
			::std::cout << "Yes" << ::std::endl;
			return 0;
		}
	}
	::std::cout << "No" << ::std::endl;
	return 0;
}