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# (Mono 4.6.2.0) (judge verdict: Runtime Error)

using System;
using System.IO;
using System.Linq;
using System.Runtime;
using System.Reflection;
using System.Diagnostics;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;
using static System.Math;

class P
{
    static void Main()
    {
        int[] nm = Console.ReadLine().Split().Select(int.Parse).ToArray();
        int n = nm[0];
        int m = nm[1];
        string s = Console.ReadLine();
        //a-aを一つの頂点として扱う
        //すべてのinfに属している頂点は、その頂点がどのinfに属しているかのdictを持つ
        //a-bを繋ぐそれが出た場合は、infとinfを繋いでいるか
        //そのグループが奇数と偶数どちらも生成可能なことが条件として必要
        //グループidみたいなのを持ってあげて、id持ちとマージした時はそれぞれの頂点に対して[id,いちばんからのindex]をもたせてあげる
        //文字ジェネレータを隣り合ってるところ両方がジェネレータと接触しているものとする
        //a-a
        //| |
        //b-b
        //これをどうにか判定してあげたい
        //a-aのとこにジェネレータ候補indexを持たせてあげて、そのジェネレータ候補がジェネレータにることがジェネレータ昇格への制約となっているものに対してindexを伝搬
        //a-aを見つけたらまずdfsを決行 dfsによって通過した頂点はジェネレータでないならばそれが保証される状態にする
        //a-a この次はbを探す この次もbを探す そしてaを探す
        //通った逆要素に接触した場合、OK
        //通った同要素に接触した場合、逆要素と接触していたらOK していなかったらcontinue
        //DFSが終点してしまったら全ての頂点群を殺す(そこからDFSで辿ってももうのぞみはないことは確定しているので)
        //次の頂点からDFSスタート

        //DFSで来てるってことは

        //AABBAABB…
        //これでDFS回すのが明らかに正解なんですが、
        //Aから始めてAABBとなるように回し、自分と違う色が求めている色の時にループが閉じるのが嬉しい(問答無用でOK)
        //なんだけど、同じ色の時に閉じてもOKな場合があるんだよな
        //同じ色の時に閉じた場合、もし閉じたところに自己ループが隣り合ってたらOK
        //自己ループから評価を始めてあげる?嘘

        //自己ループはどちらでもOKなので、


        Vertex[] vert = Enumerable.Repeat(0, n).Select(_ => new Vertex()).ToArray();
        for (int i = 0; i < s.Length; i++)
        {
            vert[i].Letter = s[i] == 'A' ? 0 : 1;
        }
        for (int i = 0; i < m; i++)
        {
            int[] xy = Console.ReadLine().Split().Select(x => int.Parse(x) - 1).ToArray();
            if(xy[0] == xy[1])
            {
                vert[xy[0]].Connections.Add(xy[1]);
                vert[xy[0]].isSelfLoop = true;
            }
            else
            {
                vert[xy[0]].Connections.Add(xy[1]);
                vert[xy[1]].Connections.Add(xy[0]);
            }
        }
        long currentVersion = 1;
        for (int i = 0; i < n; i++)
        {
            if (vert[i].Version != 0) continue;
            vert[i].Version = currentVersion;
            //index,次に欲しい色
            Stack<Tuple<int, int>> stack = new Stack<Tuple<int, int>>();
            stack.Push(new Tuple<int, int>(i, vert[i].Letter));
            if (vert[i].isSelfLoop) stack.Push(new Tuple<int, int>(i, (vert[i].Letter + 1) % 2));
            while (stack.Count != 0)
            {
                //
                var currentPos = stack.Pop();
                Debug.WriteLine(currentPos.Item1);
                //繋がってるところ全てに対して回す
                foreach (var connection in vert[currentPos.Item1].Connections)
                {
                    if (currentPos.Item1 == connection) continue;
                    //一回通過したことがあったら
                    if (vert[connection].Version == currentVersion)
                    {
                        //求めているletterと一致していたら
                        if (vert[connection].Letter == currentPos.Item2)
                        {
                            //現在の場所の文字と求めている文字が違ったら(つまり問答無用でokな奴)
                            if (vert[currentPos.Item1].Letter != currentPos.Item2)
                            {
                                Console.WriteLine("Yes");
                                return;
                            }
                            else
                            {
                                //現在のとこと求めてる文字が同じだったら
                                //お前自信が自己ループで帰ってきてたりしたら最悪
                                foreach (var item in vert[connection].Connections)
                                {
                                    if (connection == item) continue;
                                    if (vert[item].isSelfLoop)
                                    {
                                        Console.WriteLine("Yes");
                                        throw new Exception();
                                        return;
                                    }
                                }
                            }
                        }
                        continue;
                    }
                    if (vert[connection].Letter != currentPos.Item2) continue;
                    if (vert[connection].isSelfLoop && vert[currentPos.Item1].isSelfLoop)
                    {
                        Console.WriteLine("Yes");
                        return;
                    }
                    //別の時に通過したことがあったら(見込み0なので)
                    if (vert[connection].Version != 0) continue;
                    vert[connection].Version = currentVersion;
                    //次に欲しい色が今の色だったら、
                    int next = ((vert[currentPos.Item1].Letter == currentPos.Item2) ? (vert[currentPos.Item1].Letter + 1) % 2 : currentPos.Item2);
                    stack.Push(new Tuple<int, int>(connection, next));
                    if (vert[connection].isSelfLoop) stack.Push(new Tuple<int, int>(connection, (next + 1) % 2));
                }
            }
            currentVersion++;
        }
        //noと出るはずがyes
        Console.WriteLine("No");
    }
    static bool hashIsInRange(int hash)
    {
        long lower = (long)int.MaxValue * 61 / 64;
        long upper = (long)int.MaxValue * 62 / 64;
        return lower <= hash && hash <= upper;
    }
}

class Vertex
{
    public long Version = 0;
    public int Letter;
    public List<int> Connections = new List<int>();
    public bool isSelfLoop;
}