<|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.

156. Strange Graph
time limit per test: 0.25 sec.
memory limit per test: 65536 KB
input: standard input
output: standard output



Let us consider an undirected graph G = <V, E>. We say that two vertices u and v are neighbours if (u, v) in E. In this case we also say that u is a neighbour of v and v is a neighbour of u. Let us denote by N(v) the set of neighbours of v. Recall that the number of neighbours of v is called the degree of this vertex and is denoted by deg v.
We call graph G strange if it is connected and for its every vertex v the following conditions are satisfied:
  1. deg v >= 2 (i.e. there are at least two neighbours of v)
  2. if deg v = 2 then the two neighbours of v are not connected by an edge
  3. if deg v > 2 then there exists u in N(v), such that the following is true:
    (a) deg u = 2
    (b) any two diRerent vertices w1, w2 in N(v) \ {u} are neighbours, i.e. (w1,w2) in E
You are given some strange graph G. Find a hamiltonian cycle in it, i.e. a cycle that goes through every vertex of G exactly once.

Input
The first line of the input file contains two integer numbers N and M - the number of vertices and edges in G respectively (3 <= N <= 10000, M <= 100000). 2M integer numbers follow - each pair represents vertices connected by the corresponding edge (vertices are numbered from 1 to N). It is guaranteed that each edge occurs exactly once in the input file and that there are no loops (i.e. ends of each edge are distinct).

Output
If there is no hamiltonian cycle in G, print -1 in the first line of the output file. In the other case output N numbers - the sequence of vertices of G as they appear in the hamiltonian cycle found (note that the last vertex must be connected to the first one). If there are several solutions, output any one.

Sample test(s)

Input
Sample input #1
4 4
1 2 2 3 3 4 4 1

Sample input #2
9 12
1 2 2 3 3 1 1 4 2 5 3 6
4 7 5 8 6 9 7 8 8 9 9 7

Output
Sample output #1
1 2 3 4

Sample output #2
-1

Note
Author:	Andrew Stankevich
Resource:	ACM ICPC 2002-2003 NEERC, Northern Subregion
Date:	November, 2002

<|response|>
1. Abridged Problem Statement  
Given a connected undirected graph G with N vertices and M edges (3 ≤ N ≤ 10000, M ≤ 100000). G satisfies:  
• Every vertex v has deg(v) ≥ 2.  
• If deg(v) = 2, then its two neighbors are not directly adjacent.  
• If deg(v) > 2, then among v’s neighbors there is at least one u with deg(u)=2, and all the other neighbors of v form a clique.  
Find a Hamiltonian cycle in G (a simple cycle visiting every vertex exactly once and returning to the start), or report –1 if none exists.

2. Key Observations  
a. We can classify vertices into  
   – Chain‐vertices: deg(v)=2. They lie on “chains.”  
   – Hubs:       deg(v)>2. They join chains and have a clique among hub‐neighbors except for one chain‐exit.  
b. Every chain‐vertex connects exactly two vertices (both must ultimately be hubs, or else we’d violate the “non‐adjacent neighbors” condition). Thus chain‐vertices form simple paths (chains) whose endpoints are hubs.  
c. Each hub v has at least one adjacent chain‐vertex u. Following u along its chain leads to another hub w. We call v→w a “chain‐edge.”  
d. The subgraph H of hubs, with edges given by these chain‐edges, must have all connected components of even size to admit a cycle that uses each chain‐edge exactly once (an Eulerian pairing). If any component has odd number of hubs, answer is –1.  
e. Once we fix for each hub v exactly one chain‐neighbor u (and thus one outgoing chain‐edge v→w), the remaining neighbors of v are hubs that form a clique. We will use exactly one clique‐edge (v→some hub) in our Hamiltonian cycle, so that each hub contributes exactly one chain‐entry, one chain‐exit, and one clique‐edge in traversal.

3. Full Solution Approach  
Step A: Build adjacency lists; record degree of each vertex.  
Step B: Identify hubs (deg>2) and chain‐vertices (deg=2).  
Step C: Parity Check on the Hub‐Subgraph  
  • Maintain visited_hub[].  
  • For each unvisited hub v, run a DFS that visits only hubs.  
    – During this DFS at hub x, scan its neighbors.  
      * If neighbor y is a chain‐vertex, record next_node[x] = y (we only need one such y).  
      * If neighbor y is a hub and not yet visited, recurse.  
    – Return the count of hubs in this component.  
  • If any component count is odd, print –1 and stop.  
Step D: Build Hamiltonian Cycle by Special DFS  
  • Reset visited[all] = false. Prepare an empty vector cycle_list.  
  • Define dfs(u, used_clique_edge):  
    1. Mark visited[u]=true.  
    2. If u is a hub and its selected chain‐neighbor w=next_node[u] is unvisited, recurse dfs(w, false).  
    3. For every neighbor v of u not yet visited:  
       – If u is a chain‐vertex (deg=2), always do dfs(v, false).  
       – Else if u is a hub, and used_clique_edge==false and v is a hub, do dfs(v, true).  
         (This ensures each hub uses exactly one clique‐edge in the cycle.)  
    4. After visiting all possible next vertices, append u to cycle_list (post‐order).  
  • Call dfs(start=0, used_clique_edge=false).  
  • If cycle_list.size() < N, we failed to visit all vertices → print –1.  
  • Else reverse cycle_list and output vertices +1.  

Complexity: O(N+M) time and memory.

4. C++ Implementation with Detailed Comments  
```cpp
#include <bits/stdc++.h>
using namespace std;

int N, M;
vector<vector<int>> adj;
vector<int> degree_, next_node;
vector<bool> visited_hub, visited_all;
vector<int> cycle_list;

// Add undirected edge
void addEdge(int u, int v) {
    adj[u].push_back(v);
    adj[v].push_back(u);
}

// DFS among hubs to:
// 1) mark visited_hub[x]=true
// 2) choose one chain‐neighbor for next_node[x]
// 3) count hubs in this component
int dfsHub(int u) {
    visited_hub[u] = true;
    int count_hub = 1;
    for (int v : adj[u]) {
        if (degree_[v] == 2) {
            // record one adjacent chain‐vertex
            if (next_node[u] == -1) 
                next_node[u] = v;
        }
        else if (degree_[v] > 2 && !visited_hub[v]) {
            count_hub += dfsHub(v);
        }
    }
    return count_hub;
}

// Special DFS to build the Hamiltonian cycle
// u                : current vertex
// used_clique_edge : for hub u, have we already taken its one clique‐edge?
void dfsAll(int u, bool used_clique_edge) {
    visited_all[u] = true;
    // 1) If u is a hub, first follow its chosen chain‐neighbor
    if (degree_[u] > 2) {
        int w = next_node[u];
        if (w != -1 && !visited_all[w]) {
            dfsAll(w, false);
        }
    }
    // 2) Then explore other neighbors
    for (int v : adj[u]) {
        if (visited_all[v]) continue;
        if (degree_[u] == 2) {
            // chain‐vertex: always follow
            dfsAll(v, false);
        }
        else if (!used_clique_edge && degree_[v] > 2) {
            // hub→hub via exactly one clique‐edge
            dfsAll(v, true);
        }
    }
    // 3) Post‐order append
    cycle_list.push_back(u);
}

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

    cin >> N >> M;
    adj.assign(N, {});
    degree_.assign(N, 0);

    for(int i = 0; i < M; i++){
        int u, v;
        cin >> u >> v;
        --u; --v;
        addEdge(u,v);
        degree_[u]++; degree_[v]++;
    }

    // Prepare data structures for hub‐subgraph DFS
    visited_hub.assign(N, false);
    next_node.assign(N, -1);

    // Step C: Parity check among hubs
    for (int i = 0; i < N; i++){
        if (degree_[i] > 2 && !visited_hub[i]) {
            int comp_size = dfsHub(i);
            if (comp_size % 2 == 1) {
                // cannot pair chain‐edges in an Eulerian manner
                cout << -1 << "\n";
                return 0;
            }
        }
    }

    // Step D: Build the Hamiltonian cycle
    visited_all.assign(N, false);
    cycle_list.clear();
    dfsAll(0, false);

    if ((int)cycle_list.size() != N) {
        cout << -1 << "\n";
    } else {
        reverse(cycle_list.begin(), cycle_list.end());
        for (int x : cycle_list) {
            cout << x+1 << " ";
        }
        cout << "\n";
    }
    return 0;
}
```

5. Python Implementation with Detailed Comments  
```python
import sys
sys.setrecursionlimit(10**7)

def read_graph():
    N, M = map(int, sys.stdin.readline().split())
    adj = [[] for _ in range(N)]
    deg = [0]*N
    for _ in range(M):
        u, v = map(int, sys.stdin.readline().split())
        u -= 1; v -= 1
        adj[u].append(v)
        adj[v].append(u)
        deg[u] += 1
        deg[v] += 1
    return N, adj, deg

def dfs_hub(u):
    """
    DFS among hubs to:
    - mark visited_hub[u] = True
    - pick one chain‐vertex neighbor for next_node[u]
    - return count of hubs in this component
    """
    visited_hub[u] = True
    count = 1
    for v in adj[u]:
        if deg[v] == 2:
            # record a chain‐vertex exit
            if next_node[u] == -1:
                next_node[u] = v
        elif deg[v] > 2 and not visited_hub[v]:
            count += dfs_hub(v)
    return count

def dfs_all(u, used_clique_edge):
    """
    Build Hamiltonian cycle:
    - first follow the selected chain‐neighbor if any
    - then follow exactly one clique‐edge if u is a hub
    - at chain‐vertices, follow the only unvisited neighbor
    Post‐order append to cycle_list.
    """
    visited[u] = True
    if deg[u] > 2:
        w = next_node[u]
        if w != -1 and not visited[w]:
            dfs_all(w, False)

    for v in adj[u]:
        if visited[v]:
            continue
        if deg[u] == 2:
            # chain‐vertex: always go on
            dfs_all(v, False)
        elif not used_clique_edge and deg[v] > 2:
            # hub‐to‐hub clique‐edge, only once
            dfs_all(v, True)

    cycle_list.append(u)

if __name__ == "__main__":
    N, adj, deg = read_graph()

    # Step C: Parity check among hubs
    visited_hub = [False]*N
    next_node = [-1]*N
    for i in range(N):
        if deg[i] > 2 and not visited_hub[i]:
            if dfs_hub(i) % 2 == 1:
                print(-1)
                sys.exit(0)

    # Step D: Build the cycle
    visited = [False]*N
    cycle_list = []
    dfs_all(0, False)

    if len(cycle_list) != N:
        print(-1)
    else:
        cycle_list.reverse()
        # convert to 1‐based indexing
        print(" ".join(str(x+1) for x in cycle_list))
```

Explanation Summary  
By leveraging the “chain vs. hub” structure of a strange graph, we reduce the Hamiltonian cycle problem to:  
1. Checking that the hub‐only subgraph admits an Euler‐pairing (even component sizes).  
2. Performing a single specially‐ordered DFS that uses exactly one chain‐edge and one clique‐edge per hub, and visits each chain vertex exactly once. The post‐order traversal, reversed, yields the desired Hamiltonian cycle.