Problem:
Score : 1600 points

Problem Statement

There is a directed graph G with N vertices and M edges.
The vertices are numbered 1 through N, and the edges are numbered 1 through M.
Edge i is directed from x_i to y_i.
Here, x_i < y_i holds.
Also, there are no multiple edges in G.

Consider selecting a subset of the set of the M edges in G, and removing these edges from G to obtain another graph G'.
There are 2^M different possible graphs as G'.

Alice and Bob play against each other in the following game played on G'.
First, place two pieces on vertices 1 and 2, one on each.
Then, starting from Alice, Alice and Bob alternately perform the following operation:

Select an edge i such that there is a piece placed on vertex x_i, and move the piece to vertex y_i (if there are two pieces on vertex x_i, only move one). The two pieces are allowed to be placed on the same vertex.

The player loses when he/she becomes unable to perform the operation.
We assume that both players play optimally.

Among the 2^M different possible graphs as G', how many lead to Alice's victory?
Find the count modulo 10^9+7.

Constraints

2 ≤ N ≤ 15

1 ≤ M ≤ N(N-1)/2

1 ≤ x_i < y_i ≤ N

All (x_i,\ y_i) are distinct.

Input

Input is given from Standard Input in the following format:

N M
x_1 y_1
x_2 y_2
:
x_M y_M

Output

Print the number of G' that lead to Alice's victory, modulo 10^9+7.

Sample Input 1

2 1
1 2

Sample Output 1

1

The figure below shows the two possible graphs as G'.
A graph marked with ○ leads to Alice's victory, and a graph marked with × leads to Bob's victory.

Sample Input 2

3 3
1 2
1 3
2 3

Sample Output 2

6

The figure below shows the eight possible graphs as G'.

Sample Input 3

4 2
1 3
2 4

Sample Output 3

2

Sample Input 4

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

Sample Output 4

816

Solution in Java7 (OpenJDK 1.7.0) (judge verdict: Accepted)

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
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);
        PrintWriter out = new PrintWriter(outputStream);
        TaskF solver = new TaskF();
        solver.solve(1, in, out);
        out.close();
    }
 
    static class TaskF {
        static final long MODULO = (long) (1e9 + 7);
 
        public void solve(int testNumber, InputReader in, PrintWriter out) {
            int n = in.nextInt();
            int m = in.nextInt();
            int[] outgo = new int[n];
            int[] incom = new int[n];
            for (int i = 0; i < m; ++i) {
                int x = in.nextInt() - 1;
                int y = in.nextInt() - 1;
                outgo[x] |= 1 << y;
                incom[y] |= 1 << x;
            }
            int[] ways = new int[1 << n];
            for (int s = 1; s < ways.length; ++s) {
                if ((s & 3) != 3) continue;
                long cw = 0;
                outer:
                for (int t = s; t > 0; t = (t - 1) & s) {
                    if ((t & 3) == 3) continue;
                    int rem = s ^ t;
                    if ((t & 3) == 0 && ways[rem] == 0) continue;
                    long w = 1;
                    for (int u = 0; u < n; ++u)
                        if ((rem & (1 << u)) != 0) {
                            int oup = outgo[u] & t;
                            int cnt = Integer.bitCount(oup);
                            if (cnt == 0) {
                                continue outer;
                            }
                            w *= (1 << cnt) - 1;
                            w %= MODULO;
                            int inp = incom[u] & t;
                            w *= 1 << Integer.bitCount(inp);
                            w %= MODULO;
                        }
                    long ow;
                    if ((t & 3) == 0) {
                        ow = ways[rem];
                    } else {
                        ow = 1;
                        for (int u = 0; u < n; ++u)
                            if ((rem & (1 << u)) != 0) {
                                ow *= 1 << Integer.bitCount(outgo[u] & rem);
                                ow %= MODULO;
                            }
                    }
                    cw += ow * w;
                    cw %= MODULO;
                }
                ways[s] = (int) cw;
            }
            out.println(ways[ways.length - 1]);
        }
 
    }
 
    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;
 
        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }
 
        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }
 
        public int nextInt() {
            return Integer.parseInt(next());
        }
 
    }
}