#include <bits/stdc++.h>
using namespace std;
using lint = long long int;
using pint = pair<int, int>;
using plint = pair<lint, lint>;
struct fast_ios { fast_ios(){ cin.tie(0); ios::sync_with_stdio(false); cout << fixed << setprecision(20); }; } fast_ios_;
#define FOR(i, begin, end) for(int i=(begin);i<(end);i++)
#define IFOR(i, begin, end) for(int i=(end)-1;i>=(begin);i--)
#define REP(i, n) FOR(i,0,n)
#define IREP(i, n) IFOR(i,0,n)

int N, M;
string s;
constexpr int Nmax = 400000;
vector<int> to[Nmax * 2];
bitset<Nmax * 2> isGood;

void Yes()
{
    cout << "Yes" << endl;
    exit(0);
}

struct DirectedGraph
{
    int V; // 頂点数
    vector<vector<int> > to;
    vector<vector<int> > from;

    vector<bool> used;
    vector<int> vs;

    void dfs(int v)
    {
        used[v] = true;
        for (auto t : to[v]) if (!used[t]) dfs(t);
        vs.push_back(v);
    }
    void rdfs(int v, int k)
    {
        used[v] = true;
        cmp[v] = k;
        for (auto t : from[v]) if (!used[t]) rdfs(t, k);
    }

    vector<int> cmp;
    DirectedGraph(int V) : V(V),
                           to(vector<vector<int> >(V)), 
                           from(vector<vector<int> >(V)),
                           cmp(vector<int>(V))
                           {}
    void add_edge(int from_, int to_)
    {
        to[from_].push_back(to_);
        from[to_].push_back(from_);
    }

    int scc_num = -1;
    int scc()
    {
        used = vector<bool>(V, false);
        vs.clear();
        for (int v = 0; v < V; v++) if (!used[v]) dfs(v);

        used = vector<bool>(V, false);
        scc_num = 0;
        for (int i = vs.size() - 1; i >= 0; i--) if (!used[vs[i]]) rdfs(vs[i], scc_num++);
        return scc_num;
    }

    // scc()を実行したあと，強連結成分を潰したトポロジカル順序のグラフを生成
    DirectedGraph generateTopologicalGraph()
    {
        DirectedGraph newgraph(scc_num);
        REP(s, V) for (auto t : to[s])
        {
            if (cmp[s] != cmp[t]) newgraph.add_edge(cmp[s], cmp[t]);
        }
        return newgraph;
    }
};


int main()
{
    cin >> N >> M >> s;
    DirectedGraph g(N * 2);

    REP(i, M)
    {
        int a, b;
        cin >> a >> b;
        a--; b--;
        if (s[a] == s[b])
        {
            // to[a].push_back(b + N);
            // to[b].push_back(a + N);
            g.add_edge(a, b + N);
            g.add_edge(b, a + N);
        }
        else
        {
            // to[a + N].push_back(b);
            // to[b + N].push_back(a);
            g.add_edge(a + N, b);
            g.add_edge(b + N, a);
        }
    }

    // REP(i, N * 2) isGood.set(i);
    // REP(i, N * 2)
    // {
    //     set<int> visited;
    //     queue<int> tovisit;
    //     tovisit.push(i);
    //     while (!tovisit.empty())
    //     {
    //         int now = tovisit.front();
    //         tovisit.pop();
    //         if (visited.find(now) != visited.end()) Yes();
    //         visited.insert(now);
    //         for (auto v : to[now]) if (isGood[v])
    //         {
    //             tovisit.push(v);
    //         }
    //     }

    //     for (auto v : visited) isGood.reset(v);
    // }
    // cout << "No" << endl;
    if (N * 2 != g.scc()) cout << "Yes" << endl;
    else cout << "No" << endl;
}


Measured memory_bytes: 58436