Problem:
Score: 500 points

Problem Statement

Does there exist an undirected graph with N vertices satisfying the following conditions?

The graph is simple and connected.

The vertices are numbered 1, 2, ..., N.

Let M be the number of edges in the graph. The edges are numbered 1, 2, ..., M, the length of each edge is 1, and Edge i connects Vertex u_i and Vertex v_i.

There are exactly K pairs of vertices (i,\ j)\ (i < j) such that the shortest distance between them is 2.

If there exists such a graph, construct an example.

Constraints

All values in input are integers.

2 \leq N \leq 100

0 \leq K \leq \frac{N(N - 1)}{2}

Input

Input is given from Standard Input in the following format:

N K

Output

If there does not exist an undirected graph with N vertices satisfying the conditions, print -1.

If there exists such a graph, print an example in the following format (refer to Problem Statement for what the symbols stand for):

M
u_1 v_1
:
u_M v_M

If there exist multiple graphs satisfying the conditions, any of them will be accepted.

Sample Input 1

5 3

Sample Output 1

5
4 3
1 2
3 1
4 5
2 3

This graph has three pairs of vertices such that the shortest distance between them is 2: (1,\ 4), (2,\ 4), and (3,\ 5). Thus, the condition is satisfied.

Sample Input 2

5 8

Sample Output 2

-1

There is no graph satisfying the conditions.

Solution in Rust (1.15.1) (judge verdict: Accepted)

#[allow(unused_macros)]
macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        let mut next = || { iter.next().unwrap() };
        input_inner!{next, $($r)*}
    };
    ($($r:tt)*) => {
        let stdin = std::io::stdin();
        let mut bytes = std::io::Read::bytes(std::io::BufReader::new(stdin.lock()));
        let mut next = move || -> String{
            bytes
                .by_ref()
                .map(|r|r.unwrap() as char)
                .skip_while(|c|c.is_whitespace())
                .take_while(|c|!c.is_whitespace())
                .collect()
        };
        input_inner!{next, $($r)*}
    };
}

#[allow(unused_macros)]
macro_rules! input_inner {
    ($next:expr) => {};
    ($next:expr, ) => {};

    ($next:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($next, $t);
        input_inner!{$next $($r)*}
    };

    ($next:expr, mut $var:ident : $t:tt $($r:tt)*) => {
        let mut $var = read_value!($next, $t);
        input_inner!{$next $($r)*}
    };
}

#[allow(unused_macros)]
macro_rules! read_value {
    ($next:expr, ( $($t:tt),* )) => {
        ( $(read_value!($next, $t)),* )
    };

    ($next:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($next, $t)).collect::<Vec<_>>()
    };

    ($next:expr, chars) => {
        read_value!($next, String).chars().collect::<Vec<char>>()
    };

    ($next:expr, bytes) => {
        read_value!($next, String).into_bytes()
    };

    ($next:expr, usize1) => {
        read_value!($next, usize) - 1
    };

    ($next:expr, $t:ty) => {
        $next().parse::<$t>().expect("Parse error")
    };
}

#[allow(dead_code)]
struct UnionFind {
    parent: Vec<usize>,
    rank: Vec<usize>,
    size: Vec<usize>,
}

#[allow(dead_code)]
impl UnionFind {
    fn new(n: usize) -> UnionFind {
        let mut p = vec![0; n];
        for i in 0..n {
            p[i] = i;
        }
        return UnionFind {
            parent: p,
            rank: vec![0; n],
            size: vec![1; n],
        };
    }

    fn find(&mut self, x: usize) -> usize {
        if x == self.parent[x] {
            x
        } else {
            let p = self.parent[x];
            let pr = self.find(p);
            self.parent[x] = pr;
            pr
        }
    }

    fn same(&mut self, a: usize, b: usize) -> bool {
        self.find(a) == self.find(b)
    }

    fn unite(&mut self, a: usize, b: usize) {
        let a_root = self.find(a);
        let b_root = self.find(b);
        if self.rank[a_root] > self.rank[b_root] {
            self.parent[b_root] = a_root;
            self.size[a_root] += self.size[b_root];
        } else {
            self.parent[a_root] = b_root;
            self.size[b_root] += self.size[a_root];
            if self.rank[a_root] == self.rank[b_root] {
                self.rank[b_root] += 1;
            }
        }
    }

    fn get_size(&mut self, x: usize) -> usize {
        let root = self.find(x);
        self.size[root]
    }
}

fn main() {
    input! {
        n: usize,
        k: usize,
    }

    if k > (n - 1) * (n - 2) / 2 {
        println!("-1");
    } else {
        let mut e = Vec::new();
        for i in 1..n {
            e.push((0, i));
        }
        let num = (n - 1) * (n - 2) / 2 - k;
        let mut c = 0;
        'outer: for i in 1..n {
            for j in i + 1..n {
                if c < num {
                    c += 1;
                    e.push((i, j));
                }
            }
        }

        println!("{}", e.len());

        for (x, y) in e {
            println!("{} {}", x + 1, y + 1);
        }
    }
}