Problem:
Score : 100 points

Problem Statement

There are N islands floating in Ringo Sea, and M travel agents operate ships between these islands. For convenience, we will call these islands Island 1, 2, …, N, and call these agents Agent 1, 2, …, M.

The sea currents in Ringo Sea change significantly each day. Depending on the state of the sea on the day, Agent i (1 ≤ i ≤ M) operates ships from Island a_i to b_i, or Island b_i to a_i, but not both at the same time. Assume that the direction of the ships of each agent is independently selected with equal probability.

Now, Takahashi is on Island 1, and Hikuhashi is on Island 2. Let P be the probability that Takahashi and Hikuhashi can travel to the same island in the day by ships operated by the M agents, ignoring the factors such as the travel time for ships. Then, P × 2^M is an integer. Find P × 2^M modulo 10^9 + 7.

Constraints

2 ≤ N ≤ 15

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

1 ≤ a_i < b_i ≤ N

All pairs (a_i, b_i) are distinct.

Input

Input is given from Standard Input in the following format:

N M
a_1 b_1
:
a_M b_M

Output

Print the value P × 2^M modulo 10^9 + 7.

Sample Input 1

4 3
1 3
2 3
3 4

Sample Output 1

6

The 2^M = 8 scenarios shown above occur with equal probability, and Takahashi and Hikuhashi can meet on the same island in 6 of them. Thus, P = 6/2^M and P × 2^M = 6.

Sample Input 2

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

Sample Output 2

18

Sample Input 3

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

Sample Output 3

64

Solution in Rust (1.15.1) (judge verdict: Wrong Answer)

#[allow(unused_imports)]
use std::cmp::*;
#[allow(unused_imports)]
use std::collections::*;
use std::io::{Write, BufWriter};
// https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8
macro_rules! input {
    ($($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)*}
    };
}

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)*}
    };
}

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, usize1) => {
        read_value!($next, usize) - 1
    };

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

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

/// Verified by https://atcoder.jp/contests/arc093/submissions/3968098
mod mod_int {
    use std::ops::*;
    pub trait Mod: Copy { fn m() -> i64; }
    #[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
    pub struct ModInt<M> { pub x: i64, phantom: ::std::marker::PhantomData<M> }
    impl<M: Mod> ModInt<M> {
        // x >= 0
        pub fn new(x: i64) -> Self { ModInt::new_internal(x % M::m()) }
        fn new_internal(x: i64) -> Self {
            ModInt { x: x, phantom: ::std::marker::PhantomData }
        }
        pub fn pow(self, mut e: i64) -> Self {
            debug_assert!(e >= 0);
            let mut sum = ModInt::new_internal(1);
            let mut cur = self;
            while e > 0 {
                if e % 2 != 0 { sum *= cur; }
                cur *= cur;
                e /= 2;
            }
            sum
        }
        #[allow(dead_code)]
        pub fn inv(self) -> Self { self.pow(M::m() - 2) }
    }
    impl<M: Mod, T: Into<ModInt<M>>> Add<T> for ModInt<M> {
        type Output = Self;
        fn add(self, other: T) -> Self {
            let other = other.into();
            let mut sum = self.x + other.x;
            if sum >= M::m() { sum -= M::m(); }
            ModInt::new_internal(sum)
        }
    }
    impl<M: Mod, T: Into<ModInt<M>>> Sub<T> for ModInt<M> {
        type Output = Self;
        fn sub(self, other: T) -> Self {
            let other = other.into();
            let mut sum = self.x - other.x;
            if sum < 0 { sum += M::m(); }
            ModInt::new_internal(sum)
        }
    }
    impl<M: Mod, T: Into<ModInt<M>>> Mul<T> for ModInt<M> {
        type Output = Self;
        fn mul(self, other: T) -> Self { ModInt::new(self.x * other.into().x % M::m()) }
    }
    impl<M: Mod, T: Into<ModInt<M>>> AddAssign<T> for ModInt<M> {
        fn add_assign(&mut self, other: T) { *self = *self + other; }
    }
    impl<M: Mod, T: Into<ModInt<M>>> SubAssign<T> for ModInt<M> {
        fn sub_assign(&mut self, other: T) { *self = *self - other; }
    }
    impl<M: Mod, T: Into<ModInt<M>>> MulAssign<T> for ModInt<M> {
        fn mul_assign(&mut self, other: T) { *self = *self * other; }
    }
    impl<M: Mod> Neg for ModInt<M> {
        type Output = Self;
        fn neg(self) -> Self { ModInt::new(0) - self }
    }
    impl<M> ::std::fmt::Display for ModInt<M> {
        fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
            self.x.fmt(f)
        }
    }
    impl<M> ::std::fmt::Debug for ModInt<M> {
        fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
            self.x.fmt(f)
        }
    }
    impl<M: Mod> From<i64> for ModInt<M> {
        fn from(x: i64) -> Self { Self::new(x) }
    }
} // mod mod_int

macro_rules! define_mod {
    ($struct_name: ident, $modulo: expr) => {
        #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
        struct $struct_name {}
        impl mod_int::Mod for $struct_name { fn m() -> i64 { $modulo } }
    }
}
const MOD: i64 = 1_000_000_007;
define_mod!(P, MOD);
type ModInt = mod_int::ModInt<P>;

/// Generates an Iterator over subsets of univ, in the descending order. 
/// Verified by: http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=3050308
struct SubsetIter { bits: Option<usize>, univ: usize }
impl Iterator for SubsetIter {
    type Item = usize;
    fn next(&mut self) -> Option<usize> {
        match self.bits {
            None => None,
            Some(bits) => {
                let ans = bits;
                self.bits =
                    if bits == 0 { None }
                else { Some((bits - 1) & self.univ) };
                Some(ans)
            }
        }
    }
}
fn subsets(univ: usize) -> SubsetIter {
    SubsetIter { bits: Some(univ), univ: univ }
}

fn solve() {
    let out = std::io::stdout();
    let mut out = BufWriter::new(out.lock());
    macro_rules! puts {
        ($($format:tt)*) => (write!(out,$($format)*).unwrap());
    }
    input! {
        n: usize, m: usize,
        ab: [(usize1, usize1); m],
    }
    const W: usize = 1000;
    let mut pow2 = vec![ModInt::new(1); W];
    let mut invpow2 = vec![ModInt::new(1); W];
    pow2[0] = ModInt::new(1);
    invpow2[0] = ModInt::new(1);
    for i in 1..W {
        pow2[i] = pow2[i - 1] * 2;
        invpow2[i] = pow2[i].inv();
    }
    let mut induced = vec![0; 1 << n];
    for bits in 0..1 << n {
        let mut cnt = 0;
        for &(a, b) in &ab {
            if (bits & 1 << a) != 0 && (bits & 1 << b) != 0 {
                cnt += 1;
            }
        }
        induced[bits] = cnt;
    }
    let mut adj = vec![0; 1 << n];
    for bits in 0..1 << n {
        let mut cnt = 0;
        for &(a, b) in &ab {
            if ((bits & 1 << a) != 0) ^ ((bits & 1 << b) != 0) {
                cnt += 1;
            }
        }
        adj[bits] = cnt;
    }
    let mut conn = vec![ModInt::new(0); 1 << n];
    for bits in 0..1 << n {
        let mut tot = ModInt::new(0);
        for sub in subsets(bits) {
            if induced[sub] != 0 { continue; }
            let count = induced[bits] - induced[bits - sub];
            if sub.count_ones() % 2 == 1 {
                tot -= invpow2[count];
            } else {
                tot += invpow2[count];
            }
        }
        conn[bits] = tot;
    }
    // Special case: |bits| = 1
    for i in 0..n {
        conn[1 << i] = ModInt::new(1);
    }
    /*
    for bits in 0..1 << n {
        eprintln!("conn[{}] = {:?}", bits, conn[bits] * pow2[m]);
    }*/
    let mut dp1 = vec![ModInt::new(0); 1 << n];
    let mut dp2 = vec![ModInt::new(0); 1 << n];
    dp1[1] = ModInt::new(1);
    dp2[2] = ModInt::new(1);
    for bits in 1usize..1 << n {
        if bits.is_power_of_two() { continue; }
        for sub in subsets(bits) {
            if 2 * sub < bits { continue; }
            let inter = induced[bits] - induced[bits - sub] - induced[sub];
            if inter > 0 {
                dp1[bits] += dp1[bits - sub] * conn[sub] * invpow2[inter];
                dp2[bits] += dp2[bits - sub] * conn[sub] * invpow2[inter];
            }
        }
    }
    // Moebius transf
    /*
    for i in 0..n {
        for bits in 0..1 << n {
            if (bits & 1 << i) == 0 {
                dp1[bits] -= dp1[bits | 1 << i];
                dp2[bits] -= dp2[bits | 1 << i];
            }
        }
    }
     */
    /*
    for bits in 0..1 << (n - 2) {
        eprintln!("dp1[{}] = {}, dp2[{}] = {}",
                  1 + 4 * bits, dp1[1 + 4 * bits] * pow2[m],
                  2 + 4 * bits, dp2[2 + 4 * bits] * pow2[m]);
    }*/
    let mut tot = ModInt::new(0);
    for bits in 0..1 << (n - 2) {
        for sub in subsets((1 << (n - 2)) - 1 - bits) {
            let set0 = 1 + 4 * bits;
            let set1 = 2 + 4 * sub;
            let inter = induced[set0 + set1] - induced[set0] - induced[set1];
            if inter > 0 { continue; }
            tot += dp1[set0] * dp2[set1]
                * invpow2[adj[set0]] * invpow2[adj[set1]];
        }
    }
    puts!("{}\n", (-tot + 1) * pow2[m]);
}

fn main() {
    // In order to avoid potential stack overflow, spawn a new thread.
    let stack_size = 104_857_600; // 100 MB
    let thd = std::thread::Builder::new().stack_size(stack_size);
    thd.spawn(|| solve()).unwrap().join().unwrap();
}