<|instruction|>
Solve the below problem. The solution should start with an abridged problem statement. Then key observations. Then full solution based on the observations. Then C++ and Python implementations with comments.

286. Ancient decoration
Time limit per test: 0.25 second(s)
Memory limit: 65536 kilobytes
input: standard
output: standard



The ancient race ofhas built N cities connected with two-way roads. They believed in magic of an even number K and built the roads in such a way that each city had exactly K roads going from it.

The Hollars decided to decorate some roads because of their religious holiday. Because they also believe in magic of an even number 2, each city must have exactly 2 decorated roads going from it.

You have to find the roads needing to be decorated.

Input
The first line of the input contains integers N and K (2≤ KNK/2 lines contains description of one road, being the numbers of the cities connected by this road. The cities are numbered starting from 1. There is no road from a city to itself; each pair of cities is connected by at most one road.

Output
If it is impossible to decorate the roads, the only line of the output must contain 'NO' (without quotes). Otherwise the first line of the output must contain 'YES' (without quotes); the rest of the output must contain N lines, each containing one number of a road to be decorated. The roads are numbered starting from 1 in the same order as they appear in the input.

Example(s)
sample input
sample output
9 4
1 2
1 3
1 4
1 5
2 3
3 4
4 5
5 2
2 6
3 7
4 8
5 9
6 7
7 8
8 9
9 6
7 9
8 6
YES
4
9
5
3
12
13
10
11
15



Novosibirsk SU Contest #2, by Novosibirsk Team #1

<|response|>
1. Abridged problem statement  
You are given an undirected, K-regular graph on N vertices (K is even). There are M = N·K/2 edges, each indexed from 1 to M. Find a subset of exactly N edges so that every vertex is incident to exactly 2 chosen edges. If such a selection exists, output "YES" and any valid list of N edge indices (one per line); otherwise output "NO".

2. Key observations  
• A subgraph where every vertex has degree exactly 2 is called a 2-factor (a disjoint union of cycles covering all vertices).  
• In an even-regular graph one can first orient edges so that each vertex has equal out- and in-degree (i.e.\ out-degree = in-degree = K/2).  
• Once edges are oriented, consider a bipartite graph with left part L = {vertices as sources} and right part R = {vertices as sinks}. Each directed edge u→v becomes a bipartite edge (u in L)–(v in R).  
• This bipartite graph is regular of degree K/2 on both sides, so it admits a perfect matching. Selecting the matching gives each vertex exactly one outgoing and one incoming matched edge ⇒ total degree 2 in the original undirected graph.

3. Full solution approach  
Step A: Read input and build adjacency lists with edge indices.  
Step B: Find an Euler circuit in each connected component to orient edges.  
  - Maintain for each vertex a stack of its incident (unused) edges.  
  - Use Hierholzer’s algorithm: start from any vertex in a component, walk along unused edges marking them used, pushing vertices on a stack. When stuck, backtrack and record oriented edges along the backtrack direction.  
  - In the end, we obtain a list of directed edges (u→v) each annotated by its original index (1…M). Each vertex has out-degree = in-degree = K/2.  
Step C: Build a bipartite graph on 2N nodes: left side L = {0…N−1}, right side R = {0…N−1}.  
  - For each directed edge (u→v, idx), add a bipartite edge from u∈L to v∈R. Also store for u a list of pairs (v, idx) for later lookup.  
Step D: Run Hopcroft–Karp to find a maximum matching in this bipartite graph. If matching size < N, output "NO" and stop. Otherwise, matching size = N.  
Step E: For each u=0…N−1, let v = matchL[u]. Among the stored outgoing edges of u, find the one whose head is v, and record its original index. Print "YES" and those N indices (in any order or by u ascending).

Time complexity:  
  - Building adjacency and Euler tours takes O(M + N).  
  - Hopcroft–Karp runs in O(E·√V) = O((N·K/2)·√(2N)), which is efficient for typical contest limits.

4. C++ implementation with detailed comments  
```cpp
#include <bits/stdc++.h>
using namespace std;

// Hopcroft–Karp for bipartite matching
struct HopcroftKarp {
    int n, m;                         // sizes of left and right parts
    vector<vector<int>> adj;         // adj[u] = list of v's in right part
    vector<int> dist, matchL, matchR;
    HopcroftKarp(int _n, int _m): n(_n), m(_m) {
        adj.assign(n, {});
        matchL.assign(n, -1);
        matchR.assign(m, -1);
        dist.assign(n, 0);
    }
    void addEdge(int u, int v) {
        adj[u].push_back(v);
    }
    bool bfs() {
        queue<int> q;
        // initialize distances: free left vertices get dist=0
        for(int u = 0; u < n; u++) {
            if(matchL[u] < 0) {
                dist[u] = 0;
                q.push(u);
            } else {
                dist[u] = -1;
            }
        }
        bool foundAug = false;
        while(!q.empty()) {
            int u = q.front(); q.pop();
            for(int v: adj[u]) {
                int u2 = matchR[v];
                if(u2 < 0) {
                    // we can potentially augment along this path
                    foundAug = true;
                } else if(dist[u2] < 0) {
                    dist[u2] = dist[u] + 1;
                    q.push(u2);
                }
            }
        }
        return foundAug;
    }
    bool dfs(int u) {
        for(int v: adj[u]) {
            int u2 = matchR[v];
            if(u2 < 0 || (dist[u2] == dist[u] + 1 && dfs(u2))) {
                matchL[u] = v;
                matchR[v] = u;
                return true;
            }
        }
        dist[u] = -1;
        return false;
    }
    int maxMatching() {
        int result = 0;
        while(bfs()) {
            for(int u = 0; u < n; u++) {
                if(matchL[u] < 0 && dfs(u))
                    result++;
            }
        }
        return result;
    }
};

int main(){
    ios::sync_with_stdio(false);
    cin.tie(NULL);

    int N, K;
    cin >> N >> K;
    int M = N * K / 2;
    vector<int> A(M), B(M);
    for(int i = 0; i < M; i++){
        cin >> A[i] >> B[i];
        --A[i]; --B[i]; // zero-based
    }

    // Build undirected adjacency with edge indices
    vector<vector<pair<int,int>>> adj(N);
    for(int i = 0; i < M; i++){
        adj[A[i]].push_back({B[i], i});
        adj[B[i]].push_back({A[i], i});
    }

    // Hierholzer's algorithm to orient edges
    vector<bool> used(M, false);
    struct DE { int u, v, idx; };
    vector<DE> directed;
    directed.reserve(M);

    // We will do an iterative DFS per component
    vector<int> stackV, stackEi;
    for(int start = 0; start < N; start++){
        if(adj[start].empty()) continue;
        stackV.clear();
        stackEi.clear();
        stackV.push_back(start);
        while(!stackV.empty()) {
            int v = stackV.back();
            // discard used edges
            while(!adj[v].empty() && used[adj[v].back().second]) {
                adj[v].pop_back();
            }
            if(adj[v].empty()) {
                // backtrack
                stackV.pop_back();
                if(!stackEi.empty()){
                    int ei = stackEi.back();
                    stackEi.pop_back();
                    int u = stackV.back();
                    // orient edge u -> v
                    directed.push_back({u, v, ei});
                }
            } else {
                // traverse next unused edge
                auto [u, ei] = adj[v].back();
                adj[v].pop_back();
                if(used[ei]) continue;
                used[ei] = true;
                stackV.push_back(u);
                stackEi.push_back(ei);
            }
        }
    }

    // Now build bipartite graph on N + N
    HopcroftKarp hk(N, N);
    // store for each u the list of (v, edge-index+1)
    vector<vector<pair<int,int>>> outEdges(N);
    for(auto &e : directed) {
        hk.addEdge(e.u, e.v);
        // store +1 to output 1-based index
        outEdges[e.u].push_back({e.v, e.idx + 1});
    }

    // find perfect matching
    if(hk.maxMatching() < N) {
        cout << "NO\n";
        return 0;
    }

    // reconstruct selected edges
    cout << "YES\n";
    vector<int> answer(N);
    for(int u = 0; u < N; u++){
        int v = hk.matchL[u];
        // find the stored pair (v, idx)
        for(auto &p : outEdges[u]) {
            if(p.first == v) {
                answer[u] = p.second;
                break;
            }
        }
    }
    // output one index per line
    for(int x : answer) {
        cout << x << "\n";
    }
    return 0;
}
```

5. Python implementation with detailed comments  
```python
import sys
from collections import deque

sys.setrecursionlimit(10**7)
input = sys.stdin.readline

# Hopcroft–Karp on bipartite graph
class HopcroftKarp:
    def __init__(self, n, m):
        self.n, self.m = n, m
        self.adj = [[] for _ in range(n)]
        self.dist = [0]*n
        self.matchL = [-1]*n
        self.matchR = [-1]*m

    def add_edge(self, u, v):
        self.adj[u].append(v)

    def bfs(self):
        q = deque()
        for u in range(self.n):
            if self.matchL[u] < 0:
                self.dist[u] = 0
                q.append(u)
            else:
                self.dist[u] = -1
        foundAug = False
        while q:
            u = q.popleft()
            for v in self.adj[u]:
                u2 = self.matchR[v]
                if u2 < 0:
                    foundAug = True
                elif self.dist[u2] < 0:
                    self.dist[u2] = self.dist[u] + 1
                    q.append(u2)
        return foundAug

    def dfs(self, u):
        for v in self.adj[u]:
            u2 = self.matchR[v]
            if u2 < 0 or (self.dist[u2] == self.dist[u] + 1 and self.dfs(u2)):
                self.matchL[u] = v
                self.matchR[v] = u
                return True
        self.dist[u] = -1
        return False

    def max_matching(self):
        res = 0
        while self.bfs():
            for u in range(self.n):
                if self.matchL[u] < 0 and self.dfs(u):
                    res += 1
        return res

def main():
    N, K = map(int, input().split())
    M = N * K // 2
    A = [0]*M
    B = [0]*M
    for i in range(M):
        a, b = map(int, input().split())
        A[i], B[i] = a-1, b-1

    # Build adjacency with edge indices
    adj = [[] for _ in range(N)]
    for i in range(M):
        u, v = A[i], B[i]
        adj[u].append((v, i))
        adj[v].append((u, i))

    # Hierholzer to orient edges
    used = [False]*M
    directed = []  # will store tuples (u, v, edge_index)
    for start in range(N):
        if not adj[start]:
            continue
        stackV = [start]
        stackEi = []
        while stackV:
            v = stackV[-1]
            # skip used edges
            while adj[v] and used[adj[v][-1][1]]:
                adj[v].pop()
            if not adj[v]:
                stackV.pop()
                if stackEi:
                    ei = stackEi.pop()
                    u = stackV[-1]
                    directed.append((u, v, ei))
            else:
                u, ei = adj[v].pop()
                if used[ei]: continue
                used[ei] = True
                stackV.append(u)
                stackEi.append(ei)

    # Build bipartite graph on N + N
    hk = HopcroftKarp(N, N)
    outEdges = [[] for _ in range(N)]
    for u, v, ei in directed:
        hk.add_edge(u, v)
        outEdges[u].append((v, ei+1))  # store 1-based index

    # Find matching
    if hk.max_matching() < N:
        print("NO")
        return

    print("YES")
    answer = [0]*N
    for u in range(N):
        v = hk.matchL[u]
        # find stored (v, idx)
        for vv, idx in outEdges[u]:
            if vv == v:
                answer[u] = idx
                break

    # Print one per line
    print("\n".join(map(str, answer)))

if __name__ == "__main__":
    main()
```