输入时将qie存起来,将所有lun使用tarjan进行缩点,最后使用并查集, 将存起来的qie加上,看看是否能将所有点串起来

#include <bits/stdc++.h>

using namespace std;

const int N = 1e5 + 10, M = 1e6 + 10;

struct Edge{int u, v;};

int n, m;
int h[N], hs[N], e[M], ne[M], idx;
int dfn[N], low[N], timestamp;
int stk[N], top;
int id[N], dcc_cnt;
vector<int> dcc[N];

vector<Edge> qie;

bool in_ans[M];

int p[N];

vector<Edge> ans;

int find(int x) {
    if (p[x] != x) p[x] = find(p[x]);
    return p[x];
}

void merge(int x, int y) {
    int px = find(x), py = find(y);
    if (px == py) return;
    p[px] = py;
}

void add(int a, int b) {
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}

void tarjan(int u, int from) {
    dfn[u] = low[u] = ++ timestamp;
    stk[ ++ top] = u;
    
    for (int i = h[u]; i != -1; i = ne[i]) {
        int j = e[i];
        if (!dfn[j]) {
            tarjan(j, i);
            low[u] = min(low[u], low[j]);
        } else if (i != (from ^ 1)) {
            low[u] = min(low[u], dfn[j]);
        }
    }
    
    if (dfn[u] == low[u]) {
        dcc_cnt ++;
        int y;
        do {
            y = stk[top --];
            id[y] = dcc_cnt;
            dcc[dcc_cnt].push_back(y);
        } while (y != u);
    }
}

void solve() {
    cin >> n >> m;
    for (int i = 1; i <= n; i ++) h[i] = -1;
    
    for (int i = 1; i <= m; i ++) {
        int u, v; string w;
        cin >> u >> v >> w;
//         cout << u << " " << v << " " << w << endl;
        if (w == "Lun") {
            add(u, v); add(v, u);
        } else if (w == "Qie") { // 先把切边存起来
            qie.push_back((Edge){u, v});
        }
    }
    for (int i = 1; i <= n; i ++)
        if (!dfn[i])
            tarjan(i, -1);

    for (int i = 1; i <= n; i ++)
        if (!id[i]) {
            dcc_cnt ++;
            id[i] = dcc_cnt;
            dcc[dcc_cnt].push_back(i);
        }
    
    bool flag = true;
    
    for (int i = 1; i <= n; i ++) p[i] = i;
    
    for (int idx = 1; idx <= dcc_cnt; idx ++) {
        for (auto u : dcc[idx]) {
            for (int i = h[u]; i != -1; i = ne[i]) {
                int j = e[i];
                if (in_ans[i] || in_ans[i ^ 1] || id[j] != idx) continue;
                in_ans[i] = in_ans[i ^ 1] = true;
                ans.push_back((Edge) {u, j});
                merge(u, j);
            }
        }
    }
    
    for (auto e : qie) {
        if (find(e.u) == find(e.v)) continue;
        ans.push_back(e);
        merge(e.u, e.v);
    }
    
    for (int i = 1; i <= n; i ++)
        if (find(i) != find(1)) 
        {
            flag = false;
            break;
        }
    
    if (flag) {
        cout << "YES" << endl;
        cout << ans.size() << endl;
        for (auto a : ans) {
            cout << a.u << " " << a.v << endl;
        }
    } else {
        cout << "NO" << endl;
    }
//     for (int i = 1; i <= n; i ++) cout << dfn[i] << " " << low[i] << endl;
//     for (int i = 1; i <= n; i ++) {
//         for (int j = h[i]; j != -1; j = ne[j]) {
//             int k = e[j];
//             cout << k << " ";
//         }
//         cout << endl;
//     }
}

int main() {
    int t; t = 1;
    while (t --)
        solve();
}