#include using namespace std; const int MAXN = (int) 1e5 + 10; vector g[MAXN], graph[MAXN], undirectedGraph[MAXN]; int indeg[MAXN], outdeg[MAXN], visited[MAXN]; int n, m; vector > edges; //set neighbours[MAXN]; void dfs(int from) { visited[from] = true; for (int to: undirectedGraph[from]) { if (!visited[to]) { dfs(to); } } } int eulerTourExists() { for (int i = 0; i < n; i++) { indeg[i] = 0; outdeg[i] = 0; visited[i] = 0; undirectedGraph[i].clear(); } set > edgeSet; for (int from = 0; from < n; from++) { for (auto to: graph[from]) { indeg[to]++; outdeg[from]++; edgeSet.insert(make_pair(from, to)); edgeSet.insert(make_pair(to, from)); } } /* for (int i = 0; i < n; i++) { cerr << indeg[i] << " " << outdeg[i] << endl; } */ for (int i = 0; i < n; i++) { if (indeg[i] != outdeg[i]) { return false; } } for (auto it: edgeSet) { undirectedGraph[it.first].push_back(it.second); } dfs(0); for (int i = 0; i < n; i++) { if (!visited[i]) { return false; } } return true; } void sovleSubtask1() { for (int mask = 0; mask < (1 << m); mask++) { for (int i = 0; i < n; i++) { graph[i].clear(); } for (int i = 0; i < m; i++) { int from = edges[i].first, to = edges[i].second; if (mask & (1 << i)) { // don't change. graph[from].push_back(to); } else { graph[to].push_back(from); } } if (eulerTourExists()) { printf("YES\n"); for (int i = 0; i < m; i++) { int from = edges[i].first, to = edges[i].second; if (mask & (1 << i)) { printf("%d %d\n", from + 1, to + 1); } else { printf("%d %d\n", to + 1, from + 1); } } return; } } printf("NO\n"); } int main() { scanf("%d %d", &n, &m); assert(n >= 1 && n <= 100000); assert(m >= 1 && m <= 100000); set > st; for (int i = 0; i < m; i++) { int from, to; scanf("%d %d", &from, &to); assert(from >= 1 && from <= n); assert(to >= 1 && to <= n); assert(from != to); st.insert(make_pair(from, to)); from--; to--; g[from].push_back(to); edges.push_back(make_pair(from, to)); } assert(st.size() == m); sovleSubtask1(); return 0; }