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 C# (Mono 4.6.2.0) (judge verdict: Wrong Answer)

using System;
using System.IO;
using System.Collections.Generic;

namespace abc131_e
{
    class Program
    {
        static void Main(string[] args)
        {
            var items = Console.ReadLine().Split(' ');
            // 頂点数
            var n = int.Parse(items[0]);
            // 長さ2のペア
            var k = int.Parse(items[1]);

            Write(MinToMax(n, k));

            // a_b   :aとbは長さ1
            // a_._b :aとbは長さ2
            // つまり、こんな感じのグラフになる
            //          n k i
            // .        1 0 0
            // ._.      2 0 1
            // ./_.     3 1 2
            // .//_.    4 3 3
            // ./_/_.   5 4
            // .//_._.  5 4
            // .///_.   5 6 4
            // .///_.   i+1 i-1+i-2+...+2+1 i
            // 1=2*1/2
            // 3=3*2/2
            // 6=4*3/2
            // k=i*(i-1)/2=(n-1)*(n-2)/2

            //if (Directory.Exists("a"))
            //{
            //    Directory.Delete("a", true);
            //}
            //Directory.CreateDirectory("a");
            //if (Directory.Exists("b"))
            //{
            //    Directory.Delete("b", true);
            //}
            //Directory.CreateDirectory("b");
            //for (int n = 0; n < 100; n++)
            //{
            //    for (int k = 0; k < n * (n - 1) / 2; k++)
            //    {
            //        Debug($@"a\{n}_{k}.txt", MaxToMin(n, k));
            //        Debug($@"b\{n}_{k}.txt", MinToMax(n, k));
            //    }
            //}
        }

        static List<line> MaxToMin(int n, int k)
        {
            // すべての頂点を1に連結する
            var star = new List<line>();
            // kは(n-1)*(n-2)/2。この時のkが最大
            var kk = 0;
            for (int p = 2; p <= n; p++)
            {
                star.Add(new line(1, p));
                kk += star.Count - 1;
            }

            // 辺を付け替えて、kを調整する
            var prev = 2;
            var lines = new List<line>();
            // 1-2はすでに1につながっているから、動かしちゃダメ
            while (kk > k && star.Count > 1)
            {
                // 1に付いている辺を1-2から接続された直線に付け替える
                var line = star[star.Count - 1];
                star.Remove(line);
                line.u = prev;
                prev = line.v;
                lines.Add(line);
                // 1についてる辺が減ったので、kもn-1減る(1-2のみsにいることに注意)
                kk -= star.Count;
                // 直線の末尾に線が増えたので、kに1足す
                kk += 1;
            }
            lines.AddRange(star);

            if (kk != k)
            {
                lines.Clear();
            }

            return lines;
        }

        static List<line> MinToMax(int n, int k)
        {
            // すべての頂点を一直線に連結する
            var lines = new List<line>();
            lines.Add(new line { u = 1, v = 2 });
            for (int p = 2; p < n; p++)
            {
                lines.Add(new line(p, p + 1));
            }
            // kは辺の数-1。この時のkが最小
            var kk = lines.Count - 1;

            // 辺を付け替えて、kを調整する
            var star = new List<line>();
            // 1-2はすでに1につながっているから、動かしちゃダメ
            while (kk < k && lines.Count > 1)
            {
                // 末尾の辺を1に付け替える
                var line = lines[lines.Count - 1];
                lines.Remove(line);
                line.u = 1;
                star.Add(line);
                // 末尾の辺が減ったので、kも1減る
                kk -= 1;
                // 1に辺が増えたので、1に連結している点の数-1増える(1-2のみlにいることに注意)
                kk += star.Count;
            }
            lines.AddRange(star);

            if (kk != k)
            {
                lines.Clear();
            }

            return lines;
        }

        static void Write(List<line> lines)
        {
            var m = lines.Count <= 0 ? -1 : lines.Count;
            Console.WriteLine($"{m}");
            for (int i = 0; i < m; i++)
            {
                Console.WriteLine($"{lines[i].u} {lines[i].v}");
            }
        }

        static void Debug(string name, List<line> lines)
        {
            using (var writer = new StreamWriter(name))
            {
                Console.SetOut(writer);
                lines.Sort();
                Write(lines);
            }
        }
    }
    struct line : IComparable<line>
    {
        public int u;
        public int v;
        public line(int u, int v)
        {
            this.u = Math.Min(u, v);
            this.v = Math.Max(u, v);
        }
        public int CompareTo(line other)
        {
            var c = u.CompareTo(other.u);
            if (c == 0)
            {
                c = v.CompareTo(other.v);
            }
            return c;
        }
    }
}