#include <bits/stdc++.h>
using namespace std;
template <typename Arg, typename... Args>
inline void input(Arg& arg, Args&... args) {
  cin >> arg;
  (void)(int[]){0, (void(cin >> args), 0)...};
}
template <typename Arg, typename... Args>
inline void printErr(Arg&& arg, Args&&... args) {
  cerr << arg;
  (void)(int[]){0, (void(cerr << " "
                              << "\033[1;41m"
                              << ","
                              << "\033[0m"
                              << " " << args),
                    0)...};
  cerr << '\n';
};
template <class T, class... U>
void dbg(const char* sdbg, T h, U... a) {
  cerr << "\033[1;31m"
       << "Debug: "
       << "\033[0m";
  cerr << sdbg;
  cerr << " "
       << "\033[1;41m"
       << "="
       << "\033[0m"
       << " ";
  printErr(h, a...);
}
template <class S, class T>
ostream& operator<<(ostream& os, const pair<S, T>& p) {
  return os << "pair(" << p.first << "\033[1;31m"
            << ", "
            << "\033[0m" << p.second << ")";
}
template <class T>
ostream& operator<<(ostream& os, const vector<T>& p) {
  os << "\033[1;32m"
     << "vector[ "
     << "\033[0m";
  for (const auto& it : p)
    os << it << "\033[1;31m"
       << ", "
       << "\033[0m";
  return os << "\033[1;32m"
            << "]"
            << "\033[0m";
}
template <class T>
ostream& operator<<(ostream& os, const set<T>& p) {
  os << "\033[1;32m"
     << "set[ ";
  for (auto& it : p)
    os << it << "\033[1;31m"
       << ", "
       << "\033[0m";
  return os << "\033[1;32m"
            << "]"
            << "\033[0m";
}
template <class S, class T>
ostream& operator<<(ostream& os, const map<S, T>& p) {
  os << "\033[1;32m"
     << "map[ "
     << "\033[0m";
  for (auto& it : p)
    os << it << "\033[1;31m"
       << ", "
       << "\033[0m";
  return os << "\033[1;32m"
            << "]"
            << "\033[0m";
}
template <class T>
void dbgIter(const char* sdbg, T a, T b) {
  cerr << "\033[1;31m"
       << "Debug: "
       << "\033[0m";
  cerr << sdbg;
  cerr << "\033[1;31m"
       << " = "
       << "\033[0m";
  cerr << "[";
  for (T i = a; i != b; ++i) {
    if (i != a) cerr << ", ";
    cerr << *i;
  }
  cerr << "]\n";
}
template <typename T>
using min_heap = priority_queue<T, std::vector<T>, std::greater<T>>;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T, typename S>
inline bool contains(map<T, S> map1, S value1) {
  return map1.find(value1) != map1.end();
}
template <typename T, typename S>
inline bool contains(T container1, S value1) {
  return container1.find(value1) != container1.end();
}
struct DFSData {
  vector<bool> visited;
  vector<int32_t> parity;
  DFSData(int32_t vertices) {
    visited.resize(vertices, false);
    parity.resize(vertices, -1);
  }
};
struct Graph {
  struct GraphNode {
    int32_t vertex, link;
    GraphNode() : vertex{0}, link{0} {}
    GraphNode(int32_t v1, int32_t l1) : vertex{v1}, link{l1} {}
  };
  vector<GraphNode> adj;
  vector<int32_t> head;
  Graph(int32_t vertices) { head.resize(vertices, -1); }
  void add_edge(int32_t v1, int32_t v2) {
    adj.emplace_back(v2, head[v1]);
    head[v1] = adj.size() - 1;
    adj.emplace_back(v1, head[v2]);
    head[v2] = adj.size() - 1;
  }
  bool dfs(int32_t v1, DFSData& d, int32_t parity) {
    if (d.visited[v1]) {
      if (d.parity[v1] != parity) return false;
      return true;
    }
    d.visited[v1] = true;
    d.parity[v1] = parity;
    bool success = true;
    int32_t j = head[v1];
    for (; j != -1; j = adj[j].link) {
      success &= dfs(adj[j].vertex, d, !parity);
    }
    return success;
  }
};
void solve() {
  int32_t n, m;
  cin >> n >> m;
  int32_t v1, v2;
  Graph gh(n + 1);
  for (int64_t(i) = (0); (i) < (m); ++(i)) {
    input(v1, v2);
    gh.add_edge(v1, v2);
  }
  DFSData dfs_data(n + 1);
  for (int64_t(i) = (1); (i) <= (n); ++(i)) {
    if (dfs_data.visited[i]) continue;
    if (gh.dfs(i, dfs_data, 0) == false) {
      cout << "-1\n";
      return;
    }
  }
  vector<int32_t> vertexCover[2];
  for (int64_t(i) = (1); (i) <= (n); ++(i)) {
    if (gh.head[i] == (-1)) continue;
    vertexCover[dfs_data.parity[i]].push_back(i);
  }
  for (int64_t(i) = (0); (i) < (2); ++(i)) {
    cout << vertexCover[i].size() << '\n';
    for (const int32_t& j : vertexCover[i]) cout << j << " ";
    cout << '\n';
  }
}
int32_t main() {
  std::ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  cout.tie(nullptr);
  cout.precision(20);
  cout << fixed;
  solve();
  return 0;
}
