Problem:
Score : 300 points

Problem Statement

In Takahashi Kingdom, there is an archipelago of N islands, called Takahashi Islands.
For convenience, we will call them Island 1, Island 2, ..., Island N.

There are M kinds of regular boat services between these islands.
Each service connects two islands. The i-th service connects Island a_i and Island b_i.

Cat Snuke is on Island 1 now, and wants to go to Island N.
However, it turned out that there is no boat service from Island 1 to Island N, so he wants to know whether it is possible to go to Island N by using two boat services.

Help him.

Constraints

3 ≤ N ≤ 200 000

1 ≤ M ≤ 200 000

1 ≤ a_i < b_i ≤ N

(a_i, b_i) \neq (1, N)

If i \neq j, (a_i, b_i) \neq (a_j, b_j).

Input

Input is given from Standard Input in the following format:

N M
a_1 b_1
a_2 b_2
:
a_M b_M

Output

If it is possible to go to Island N by using two boat services, print POSSIBLE; otherwise, print IMPOSSIBLE.

Sample Input 1

3 2
1 2
2 3

Sample Output 1

POSSIBLE

Sample Input 2

4 3
1 2
2 3
3 4

Sample Output 2

IMPOSSIBLE

You have to use three boat services to get to Island 4.

Sample Input 3

100000 1
1 99999

Sample Output 3

IMPOSSIBLE

Sample Input 4

5 5
1 3
4 5
2 3
2 4
1 4

Sample Output 4

POSSIBLE

You can get to Island 5 by using two boat services: Island 1 -> Island 4 -> Island 5.

Solution in Java8 (OpenJDK 1.8.0) (judge verdict: Accepted)

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Iterator;
import java.io.BufferedWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.util.NoSuchElementException;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main
{
    public static void main(String[] args)
    {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        OutputWriter out = new OutputWriter(outputStream);
        TaskC solver = new TaskC();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskC
    {
        public void solve(int testNumber, InputReader in, OutputWriter out)
        {
            int n = in.readInt();
            int m = in.readInt();
            Graph g = new BidirectionalGraph(n);
            for (int i = 0; i < m; i++)
            {
                int u = in.readInt() - 1;
                int v = in.readInt() - 1;
                g.addWeightedEdge(u, v, 1);
                g.addWeightedEdge(v, u, 1);
            }
            long[] dist = ShortestDistance.dijkstraAlgorithm(g, 0).first;
            if (dist[n - 1] <= 2)
            {
                out.printLine("POSSIBLE");
            } else
            {
                out.printLine("IMPOSSIBLE");
            }
        }

    }

    static class InputReader
    {
        private InputStream stream;
        private byte[] buf = new byte[1024];
        private int curChar;
        private int numChars;
        private InputReader.SpaceCharFilter filter;

        public InputReader(InputStream stream)
        {
            this.stream = stream;
        }

        public int read()
        {
            if (numChars == -1)
            {
                throw new InputMismatchException();
            }
            if (curChar >= numChars)
            {
                curChar = 0;
                try
                {
                    numChars = stream.read(buf);
                } catch (IOException e)
                {
                    throw new InputMismatchException();
                }
                if (numChars <= 0)
                {
                    return -1;
                }
            }
            return buf[curChar++];
        }

        public int readInt()
        {
            int c = read();
            while (isSpaceChar(c))
            {
                c = read();
            }
            int sgn = 1;
            if (c == '-')
            {
                sgn = -1;
                c = read();
            }
            int res = 0;
            do
            {
                if (c < '0' || c > '9')
                {
                    throw new InputMismatchException();
                }
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public boolean isSpaceChar(int c)
        {
            if (filter != null)
            {
                return filter.isSpaceChar(c);
            }
            return isWhitespace(c);
        }

        public static boolean isWhitespace(int c)
        {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

        public interface SpaceCharFilter
        {
            public boolean isSpaceChar(int ch);

        }

    }

    static interface Edge
    {
    }

    static class Graph
    {
        public static final int REMOVED_BIT = 0;
        protected int vertexCount;
        protected int edgeCount;
        private int[] firstOutbound;
        private int[] firstInbound;
        private Edge[] edges;
        private int[] nextInbound;
        private int[] nextOutbound;
        private int[] from;
        private int[] to;
        private long[] weight;
        public long[] capacity;
        private int[] reverseEdge;
        private int[] flags;

        public Graph(int vertexCount)
        {
            this(vertexCount, vertexCount);
        }

        public Graph(int vertexCount, int edgeCapacity)
        {
            this.vertexCount = vertexCount;
            firstOutbound = new int[vertexCount];
            Arrays.fill(firstOutbound, -1);

            from = new int[edgeCapacity];
            to = new int[edgeCapacity];
            nextOutbound = new int[edgeCapacity];
            flags = new int[edgeCapacity];
        }

        public int addEdge(int fromID, int toID, long weight, long capacity, int reverseEdge)
        {
            ensureEdgeCapacity(edgeCount + 1);
            if (firstOutbound[fromID] != -1)
            {
                nextOutbound[edgeCount] = firstOutbound[fromID];
            } else
            {
                nextOutbound[edgeCount] = -1;
            }
            firstOutbound[fromID] = edgeCount;
            if (firstInbound != null)
            {
                if (firstInbound[toID] != -1)
                {
                    nextInbound[edgeCount] = firstInbound[toID];
                } else
                {
                    nextInbound[edgeCount] = -1;
                }
                firstInbound[toID] = edgeCount;
            }
            this.from[edgeCount] = fromID;
            this.to[edgeCount] = toID;
            if (capacity != 0)
            {
                if (this.capacity == null)
                {
                    this.capacity = new long[from.length];
                }
                this.capacity[edgeCount] = capacity;
            }
            if (weight != 0)
            {
                if (this.weight == null)
                {
                    this.weight = new long[from.length];
                }
                this.weight[edgeCount] = weight;
            }
            if (reverseEdge != -1)
            {
                if (this.reverseEdge == null)
                {
                    this.reverseEdge = new int[from.length];
                    Arrays.fill(this.reverseEdge, 0, edgeCount, -1);
                }
                this.reverseEdge[edgeCount] = reverseEdge;
            }
            if (edges != null)
            {
                edges[edgeCount] = createEdge(edgeCount);
            }
            return edgeCount++;
        }

        protected final GraphEdge createEdge(int id)
        {
            return new GraphEdge(id);
        }

        public final int addFlowWeightedEdge(int from, int to, long weight, long capacity)
        {
            if (capacity == 0)
            {
                return addEdge(from, to, weight, 0, -1);
            } else
            {
                int lastEdgeCount = edgeCount;
                addEdge(to, from, -weight, 0, lastEdgeCount + entriesPerEdge());
                return addEdge(from, to, weight, capacity, lastEdgeCount);
            }
        }

        protected int entriesPerEdge()
        {
            return 1;
        }

        public final int addWeightedEdge(int from, int to, long weight)
        {
            return addFlowWeightedEdge(from, to, weight, 0);
        }

        public final int vertexCount()
        {
            return vertexCount;
        }

        protected final int edgeCapacity()
        {
            return from.length;
        }

        public final int firstOutbound(int vertex)
        {
            int id = firstOutbound[vertex];
            while (id != -1 && isRemoved(id))
            {
                id = nextOutbound[id];
            }
            return id;
        }

        public final int nextOutbound(int id)
        {
            id = nextOutbound[id];
            while (id != -1 && isRemoved(id))
            {
                id = nextOutbound[id];
            }
            return id;
        }

        public final int destination(int id)
        {
            return to[id];
        }

        public final long weight(int id)
        {
            if (weight == null)
            {
                return 0;
            }
            return weight[id];
        }

        public final boolean flag(int id, int bit)
        {
            return (flags[id] >> bit & 1) != 0;
        }

        public final boolean isRemoved(int id)
        {
            return flag(id, REMOVED_BIT);
        }

        protected void ensureEdgeCapacity(int size)
        {
            if (from.length < size)
            {
                int newSize = Math.max(size, 2 * from.length);
                if (edges != null)
                {
                    edges = resize(edges, newSize);
                }
                from = resize(from, newSize);
                to = resize(to, newSize);
                nextOutbound = resize(nextOutbound, newSize);
                if (nextInbound != null)
                {
                    nextInbound = resize(nextInbound, newSize);
                }
                if (weight != null)
                {
                    weight = resize(weight, newSize);
                }
                if (capacity != null)
                {
                    capacity = resize(capacity, newSize);
                }
                if (reverseEdge != null)
                {
                    reverseEdge = resize(reverseEdge, newSize);
                }
                flags = resize(flags, newSize);
            }
        }

        protected final int[] resize(int[] array, int size)
        {
            int[] newArray = new int[size];
            System.arraycopy(array, 0, newArray, 0, array.length);
            return newArray;
        }

        private long[] resize(long[] array, int size)
        {
            long[] newArray = new long[size];
            System.arraycopy(array, 0, newArray, 0, array.length);
            return newArray;
        }

        private Edge[] resize(Edge[] array, int size)
        {
            Edge[] newArray = new Edge[size];
            System.arraycopy(array, 0, newArray, 0, array.length);
            return newArray;
        }

        public final boolean isSparse()
        {
            return vertexCount == 0 || edgeCount * 20 / vertexCount <= vertexCount;
        }

        protected class GraphEdge implements Edge
        {
            protected int id;

            protected GraphEdge(int id)
            {
                this.id = id;
            }

        }

    }

    static class OutputWriter
    {
        private final PrintWriter writer;

        public OutputWriter(OutputStream outputStream)
        {
            writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
        }

        public OutputWriter(Writer writer)
        {
            this.writer = new PrintWriter(writer);
        }

        public void print(Object... objects)
        {
            for (int i = 0; i < objects.length; i++)
            {
                if (i != 0)
                {
                    writer.print(' ');
                }
                writer.print(objects[i]);
            }
        }

        public void printLine(Object... objects)
        {
            print(objects);
            writer.println();
        }

        public void close()
        {
            writer.close();
        }

    }

    static interface IntQueue extends IntCollection
    {
    }

    static class Pair<U, V> implements Comparable<Pair<U, V>>
    {
        public final U first;
        public final V second;

        public static <U, V> Pair<U, V> makePair(U first, V second)
        {
            return new Pair<U, V>(first, second);
        }

        private Pair(U first, V second)
        {
            this.first = first;
            this.second = second;
        }


        public boolean equals(Object o)
        {
            if (this == o)
            {
                return true;
            }
            if (o == null || getClass() != o.getClass())
            {
                return false;
            }

            Pair pair = (Pair) o;

            return !(first != null ? !first.equals(pair.first) : pair.first != null) &&
                    !(second != null ? !second.equals(pair.second) : pair.second != null);
        }


        public int hashCode()
        {
            int result = first != null ? first.hashCode() : 0;
            result = 31 * result + (second != null ? second.hashCode() : 0);
            return result;
        }


        public String toString()
        {
            return "(" + first + "," + second + ")";
        }

        @SuppressWarnings({"unchecked"})
        public int compareTo(Pair<U, V> o)
        {
            int value = ((Comparable<U>) first).compareTo(o.first);
            if (value != 0)
            {
                return value;
            }
            return ((Comparable<V>) second).compareTo(o.second);
        }

    }

    static interface IntStream extends Iterable<Integer>, Comparable<IntStream>
    {
        public IntIterator intIterator();

        default public Iterator<Integer> iterator()
        {
            return new Iterator<Integer>()
            {
                private IntIterator it = intIterator();

                public boolean hasNext()
                {
                    return it.isValid();
                }

                public Integer next()
                {
                    int result = it.value();
                    it.advance();
                    return result;
                }
            };
        }

        default public int compareTo(IntStream c)
        {
            IntIterator it = intIterator();
            IntIterator jt = c.intIterator();
            while (it.isValid() && jt.isValid())
            {
                int i = it.value();
                int j = jt.value();
                if (i < j)
                {
                    return -1;
                } else if (i > j)
                {
                    return 1;
                }
                it.advance();
                jt.advance();
            }
            if (it.isValid())
            {
                return 1;
            }
            if (jt.isValid())
            {
                return -1;
            }
            return 0;
        }

    }

    static interface IntComparator
    {
        public static final IntComparator DEFAULT = (first, second) ->
        {
            if (first < second)
            {
                return -1;
            }
            if (first > second)
            {
                return 1;
            }
            return 0;
        };

        public int compare(int first, int second);

    }

    static interface IntIterator
    {
        public int value() throws NoSuchElementException;

        public boolean advance();

        public boolean isValid();

    }

    static class BidirectionalGraph extends Graph
    {
        public int[] transposedEdge;

        public BidirectionalGraph(int vertexCount)
        {
            this(vertexCount, vertexCount);
        }

        public BidirectionalGraph(int vertexCount, int edgeCapacity)
        {
            super(vertexCount, 2 * edgeCapacity);
            transposedEdge = new int[2 * edgeCapacity];
        }


        public int addEdge(int fromID, int toID, long weight, long capacity, int reverseEdge)
        {
            int lastEdgeCount = edgeCount;
            super.addEdge(fromID, toID, weight, capacity, reverseEdge);
            super.addEdge(toID, fromID, weight, capacity, reverseEdge == -1 ? -1 : reverseEdge + 1);
            this.transposedEdge[lastEdgeCount] = lastEdgeCount + 1;
            this.transposedEdge[lastEdgeCount + 1] = lastEdgeCount;
            return lastEdgeCount;
        }


        protected int entriesPerEdge()
        {
            return 2;
        }


        protected void ensureEdgeCapacity(int size)
        {
            if (size > edgeCapacity())
            {
                super.ensureEdgeCapacity(size);
                transposedEdge = resize(transposedEdge, edgeCapacity());
            }
        }

    }

    static interface IntCollection extends IntStream
    {
    }

    static class IntegerUtils
    {
        public static int longCompare(long a, long b)
        {
            if (a < b)
            {
                return -1;
            }
            if (a > b)
            {
                return 1;
            }
            return 0;
        }

    }

    static class ShortestDistance
    {
        public static Pair<long[], int[]> dijkstraAlgorithm(Graph graph, int source)
        {
            int vertexCount = graph.vertexCount();
            final long[] distance = new long[vertexCount];
            int[] last = new int[vertexCount];
            Arrays.fill(distance, Long.MAX_VALUE);
            Arrays.fill(last, -1);
            distance[source] = 0;
            if (graph.isSparse())
            {
                Heap heap = new Heap(vertexCount, new IntComparator()
                {
                    public int compare(int first, int second)
                    {
                        return IntegerUtils.longCompare(distance[first], distance[second]);
                    }
                }, vertexCount);
                heap.add(source);
                while (!heap.isEmpty())
                {
                    int current = heap.poll();
                    int id = graph.firstOutbound(current);
                    while (id != -1)
                    {
                        int next = graph.destination(id);
                        long total = graph.weight(id) + distance[current];
                        if (distance[next] > total)
                        {
                            distance[next] = total;
                            if (heap.getIndex(next) == -1)
                            {
                                heap.add(next);
                            } else
                            {
                                heap.shiftUp(heap.getIndex(next));
                            }
                            last[next] = id;
                        }
                        id = graph.nextOutbound(id);
                    }
                }
            } else
            {
                boolean[] visited = new boolean[vertexCount];
                for (int i = 0; i < vertexCount; i++)
                {
                    int index = -1;
                    long length = Long.MAX_VALUE;
                    for (int j = 0; j < vertexCount; j++)
                    {
                        if (!visited[j] && distance[j] < length)
                        {
                            length = distance[j];
                            index = j;
                        }
                    }
                    if (index == -1)
                    {
                        break;
                    }
                    visited[index] = true;
                    int id = graph.firstOutbound(index);
                    while (id != -1)
                    {
                        int next = graph.destination(id);
                        if (!visited[next])
                        {
                            long total = graph.weight(id) + length;
                            if (distance[next] > total)
                            {
                                distance[next] = total;
                                last[next] = id;
                            }
                        }
                        id = graph.nextOutbound(id);
                    }
                }
            }
            return Pair.makePair(distance, last);
        }

    }

    static class Heap implements IntQueue
    {
        private IntComparator comparator;
        private int size = 0;
        private int[] elements;
        private int[] at;

        public Heap(int maxElement)
        {
            this(10, maxElement);
        }

        public Heap(IntComparator comparator, int maxElement)
        {
            this(10, comparator, maxElement);
        }

        public Heap(int capacity, int maxElement)
        {
            this(capacity, IntComparator.DEFAULT, maxElement);
        }

        public Heap(int capacity, IntComparator comparator, int maxElement)
        {
            this.comparator = comparator;
            elements = new int[capacity];
            at = new int[maxElement];
            Arrays.fill(at, -1);
        }

        public boolean isEmpty()
        {
            return size == 0;
        }

        public void add(int element)
        {
            ensureCapacity(size + 1);
            elements[size] = element;
            at[element] = size;
            shiftUp(size++);
        }

        public void shiftUp(int index)
        {
            //		if (index < 0 || index >= size)
            //			throw new IllegalArgumentException();
            int value = elements[index];
            while (index != 0)
            {
                int parent = (index - 1) >>> 1;
                int parentValue = elements[parent];
                if (comparator.compare(parentValue, value) <= 0)
                {
                    elements[index] = value;
                    at[value] = index;
                    return;
                }
                elements[index] = parentValue;
                at[parentValue] = index;
                index = parent;
            }
            elements[0] = value;
            at[value] = 0;
        }

        public void shiftDown(int index)
        {
            if (index < 0 || index >= size)
            {
                throw new IllegalArgumentException();
            }
            while (true)
            {
                int child = (index << 1) + 1;
                if (child >= size)
                {
                    return;
                }
                if (child + 1 < size && comparator.compare(elements[child], elements[child + 1]) > 0)
                {
                    child++;
                }
                if (comparator.compare(elements[index], elements[child]) <= 0)
                {
                    return;
                }
                swap(index, child);
                index = child;
            }
        }

        public int getIndex(int element)
        {
            return at[element];
        }

        private void swap(int first, int second)
        {
            int temp = elements[first];
            elements[first] = elements[second];
            elements[second] = temp;
            at[elements[first]] = first;
            at[elements[second]] = second;
        }

        private void ensureCapacity(int size)
        {
            if (elements.length < size)
            {
                int[] oldElements = elements;
                elements = new int[Math.max(2 * elements.length, size)];
                System.arraycopy(oldElements, 0, elements, 0, this.size);
            }
        }

        public int poll()
        {
            if (isEmpty())
            {
                throw new IndexOutOfBoundsException();
            }
            int result = elements[0];
            at[result] = -1;
            if (size == 1)
            {
                size = 0;
                return result;
            }
            elements[0] = elements[--size];
            at[elements[0]] = 0;
            shiftDown(0);
            return result;
        }


        public IntIterator intIterator()
        {
            return new IntIterator()
            {
                private int at;


                public int value() throws NoSuchElementException
                {
                    return elements[at];
                }


                public boolean advance() throws NoSuchElementException
                {
                    return ++at < size;
                }


                public boolean isValid()
                {
                    return at < size;
                }


                public void remove() throws NoSuchElementException
                {
                    throw new UnsupportedOperationException();
                }
            };
        }

    }
}