Problem:
Problem Statement
"Everlasting -One-" is an award-winning online game launched this year. This game has rapidly become famous for its large number of characters you can play.
In this game, a character is characterized by
attributes
. There are $N$ attributes in this game, numbered $1$ through $N$. Each attribute takes one of the two states,
light
or
darkness
. It means there are $2^N$ kinds of characters in this game.
You can change your character by job change. Although this is the only way to change your character's attributes, it is allowed to change jobs as many times as you want.
The rule of job change is a bit complex. It is possible to change a character from $A$ to $B$ if and only if there exist two attributes $a$ and $b$ such that they satisfy the following four conditions:
The state of attribute $a$ of character $A$ is
light
.
The state of attribute $b$ of character $B$ is
light
.
There exists no attribute $c$ such that both characters $A$ and $B$ have the
light
state of attribute $c$.
A pair of attribute $(a, b)$ is
compatible
.
Here, we say a pair of attribute $(a, b)$ is
compatible
if there exists a sequence of attributes $c_1, c_2, \ldots, c_n$ satisfying the following three conditions:
$c_1 = a$.
$c_n = b$.
Either $(c_i, c_{i+1})$ or $(c_{i+1}, c_i)$ is a special pair for all $i = 1, 2, \ldots, n-1$. You will be given the list of special pairs.
Since you love this game with enthusiasm, you are trying to play the game with all characters (it's really crazy). However, you have immediately noticed that one character can be changed to a limited set of characters with this game's job change rule. We say character $A$ and $B$ are
essentially different
if you cannot change character $A$ into character $B$ by repeating job changes.
Then, the following natural question arises; how many essentially different characters are there?
Since the output may be very large, you should calculate the answer modulo $1{,}000{,}000{,}007$.
Input
The input is a sequence of datasets.
The number of datasets is not more than $50$ and the total size of input is less than $5$ MB.
Each dataset is formatted as follows.
$N$ $M$
$a_1$ $b_1$
:
:
$a_M$ $b_M$
The first line of each dataset contains two integers $N$ and $M$ ($1 \le N \le 10^5$ and $0 \le M \le 10^5$).
Then $M$ lines follow.
The $i$-th line contains two integers $a_i$ and $b_i$ ($1 \le a_i \lt b_i \le N$) which denote the $i$-th special pair.
The input is terminated by two zeroes.
It is guaranteed that $(a_i, b_i) \ne (a_j, b_j)$ if $i \ne j$.
Output
For each dataset, output the number of essentially different characters modulo $1{,}000{,}000{,}007$.
Sample Input
3 2
1 2
2 3
5 0
100000 0
0 0
Output for the Sample Input
3
32
607723520

Submitted solutions:

code_snippet: #include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <stack>
#include <bitset>
#define maxn 100009
using namespace std;
const int MOD=1e9+7;
int p[maxn];
long long bin[maxn];
int findset(int x)
{
	return x==p[x]?x:p[x]=findset(p[x]);
}
void unionset(int x,int y)
{
	 p[findset(x)]=findset(y);
}
int main()
{
	int n,m,x,y;
	bin[0]=1;
	for(int i=1;i<maxn;i++)
		bin[i]=2*bin[i-1]%MOD;
	while(scanf("%d%d",&n,&m)!=EOF&&n+m)
	{
		for(int i=0;i<=n;i++)
			p[i]=i;
		for(int i=0;i<m;i++)
		{
			scanf("%d%d",&x,&y);
			unionset(x,y);
		}
		int cnt=0;
		for(int i=1;i<=n;i++)
		{
			if(p[i]==i)
			{
				cnt++;
			}
		}
		int ans=bin[cnt];
		if(cnt!=n)
			ans=(ans+1)%MOD;
		printf("%d\n",ans);
	}
	return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 4660
final_rank: 12

code_snippet: // AOJ #2568 Everlasting -One-
// 2025.3.18

#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7;

struct UnionFind
{
    vector< int > data;
    UnionFind(int sz) {
        data.assign(sz, -1);
    }
    int find(int k) {
        if(data[k] < 0) return(k);
        return(data[k] = find(data[k]));
    }
    void unite(int x, int y) {
        x = find(x), y = find(y);
        if(x != y) {
            if(data[x] > data[y]) swap(x, y);
            data[x] += data[y];
            data[y] = x;
        }
    }
};

const int MAXN = 100000;
int p2[MAXN+5];

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);

    int N, M;
    p2[0] = 1;
    for(int i = 1; i <= MAXN; i++) p2[i] = 2LL * p2[i - 1] % mod;

    while(true) {
        cin >> N >> M;
        if (N == 0) break;

        UnionFind tree(N);
        for(int i = 0; i < M; i++) {
            int x, y;
            cin >> x >> y;
            tree.unite(--x, --y);
        }
        int group = 0;
        for(int i = 0; i < N; i++) group += tree.find(i) == i;
        cout << p2[group] + (group != N) << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 3928
final_rank: 5

code_snippet: #include <iostream>
#include <vector>

const long long MOD{1000000007};

const int MAX{100000};
long long P2[MAX + 1];

long long solve(int N, int M) {
    std::vector<std::vector<int>> g(N); 
    for (int i{} ; i < M ; i++) {
        int u, v;
        std::cin >> u >> v;
        u--; v--;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    int cnt{};
    std::vector<bool> vis(N);
    auto dfs{[&](auto dfs, int v) -> void {
        vis[v] = true;
        for (auto x : g[v]) if (!vis[x]) dfs(dfs, x);
    }};
    for (int i{} ; i < N ; i++) if (!vis[i]) {
        cnt++;
        dfs(dfs, i);
    }
    if (N == 1) return 2;
    else if (M == 0) return P2[N];
    else return P2[cnt] + 1;
}

int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);
    P2[0] = 1;
    for (int i{1} ; i <= MAX ; i++) {
        P2[i] = (P2[i - 1] * 2) % MOD;
    }
    while (true) {
        int N, M;
        std::cin >> N >> M;
        if (N == 0 and M == 0) break;
        std::cout << solve(N, M) << '\n';
    }
}
accuracy: 1
time_ms: 80
memory_kb: 10532
final_rank: 17

code_snippet: #line 2 "cp-library/src/cp-template.hpp"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using uint = unsigned int;
using ull  = unsigned long long;
using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128_t;
template < class T > bool chmin(T& a, T b) { if(a > b) { a = b; return true; } return false; }
template < class T > bool chmax(T& a, T b) { if(a < b) { a = b; return true; } return false; }
template < class T, class U > T ceil (T x, U y) { return (x > 0 ? (x + y - 1) / y :           x / y); }
template < class T, class U > T floor(T x, U y) { return (x > 0 ?           x / y : (x - y + 1) / y); }
int popcnt(i32 x) { return __builtin_popcount(x); }
int popcnt(u32 x) { return __builtin_popcount(x); }
int popcnt(i64 x) { return __builtin_popcountll(x); }
int popcnt(u64 x) { return __builtin_popcountll(x); }

#line 2 "cp-library/src/utility/rep_itr.hpp"
template < class T > struct itr_rep {
    T i, d;
    constexpr itr_rep(const T i) noexcept : i(i), d(1) {}
    constexpr itr_rep(const T i, const T d) noexcept : i(i), d(d) {}
    void operator++() noexcept { i += d; }
    constexpr int operator*() const noexcept { return i; }
    constexpr bool operator!=(const itr_rep x) const noexcept { return d > 0 ? i < x.i : i > x.i; }
};

template < class T > struct rep {
    const itr_rep< T > s, t;
    constexpr rep(const T t) noexcept : s(0), t(t) {}
    constexpr rep(const T s, const T t) noexcept : s(s), t(t) {}
    constexpr rep(const T s, const T t, const T d) noexcept : s(s, d), t(t, d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};

template < class T > struct revrep {
    const itr_rep < T > s, t;
    constexpr revrep(const T t) noexcept : s(t - 1, -1), t(-1, -1) {}
    constexpr revrep(const T s, const T t) noexcept : s(t - 1, -1), t(s - 1, -1) {}
    constexpr revrep(const T s, const T t, const T d) noexcept : s(t - 1, -d), t(s - 1, -d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};
#line 3 "cp-library/src/utility/io.hpp"

/* 128bit integer */
istream& operator>>(istream& is, i128& x) {
    std::string s; is >> s;
    int pm = (s[0] == '-');
    x = 0;
    for(int i : rep(pm, int(s.size()))) x = x * 10 + (s[i] - '0');
    if(pm) x *= -1;
    return is;
}
ostream& operator<<(ostream& os, const i128& x) {
    if(x == 0) return os << '0';
    i128 y = x;
    if(y < 0) { os << '-'; y *= -1; }
    std::vector<int> ny;
    while(y > 0) { ny.push_back(y % 10); y /= 10; }
    for(int i : revrep(ny.size())) os << ny[i];
    return os;
}

template < class S, class T > istream& operator>>(istream& is,       std::pair< S, T >& x) { is >> x.first        >> x.second; return is; }
template < class S, class T > ostream& operator<<(ostream& os, const std::pair< S, T >& x) { os << x.first << " " << x.second; return os; }

namespace scanner {
    struct sca {
        template < class T > operator T() {
            T s; std::cin >> s; return s;
        }
    };
    struct vec {
        int n;
        vec(int n) : n(n) {}
        template < class T > operator std::vector< T >() {
            std::vector< T > v(n);
            for(T& x : v) std::cin >> x;
            return v;
        }
    };
    struct mat {
        int h, w;
        mat(int h, int w) : h(h), w(w) {}
        template < class T > operator std::vector< std::vector< T > >() {
            std::vector m(h, std::vector< T >(w));
            for(std::vector< T >& v : m) for(T& x : v) std::cin >> x;
            return m;
        }
    };
    struct speedup {
        speedup() {
            std::cin.tie(0);
            std::ios::sync_with_stdio(0);
        }
    } speedup_instance;
}
scanner::sca in() { return scanner::sca(); }
scanner::vec in(int n) { return scanner::vec(n); }
scanner::mat in(int h, int w) { return scanner::mat(h, w); }

namespace printer {
    void precision(int d) { std::cout << std::fixed << std::setprecision(d); }
    void flush() { std::cout.flush(); }
}

template < class T >
ostream& operator<<(ostream& os, const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) { os << a[i]; if(i != n - 1) os << ' '; }
    return os;
}

int print() { std::cout << '\n'; return 0; }
template < class head, class... tail > int print(head&& h, tail&&... t) {
    std::cout << h; if(sizeof...(tail)) std::cout << ' ';
    return print(std::forward<tail>(t)...);
}
template < class T > int print_n(const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) std::cout << a[i] << "\n";
    return 0;
}


#line 2 "cp-library/src/utility/key_val.hpp"

template < class K, class V >
struct key_val {
    K key; V val;
    key_val() {}
    key_val(K key, V val) : key(key), val(val) {}
    template < std::size_t Index >
    std::tuple_element_t< Index, key_val >& get() {
        if constexpr (Index == 0) return key;
        if constexpr (Index == 1) return val;
    }
};

namespace std {

template < class K, class V > struct tuple_size < key_val< K, V > > : integral_constant< size_t, 2 > {};
template < class K, class V > struct tuple_element < 0, key_val< K, V > > { using type = K; };
template < class K, class V > struct tuple_element < 1, key_val< K, V > > { using type = V; };

}
#line 2 "cp-library/src/utility/vec_op.hpp"
template < class T > key_val< int, T > max_of(const vector< T >& a) {
    int i = std::max_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class T > key_val< int, T > min_of(const vector< T >& a) {
    int i = std::min_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class S, class T > S sum_of(const vector< T >& a) {
    S sum = 0;
    for(const T x : a) sum += x;
    return sum;
}
template < class S, class T > vector< S > freq_of(const vector< T >& a, T L, T R) {
    vector< S > res(R - L, S(0));
    for(const T x : a) res[x - L] += 1;
    return res;
}
template < class S, class T > struct prefix_sum {
    vector< S > s;
    prefix_sum(const vector< T >& a) : s(a) {
        s.insert(s.begin(), S(0));
        for(int i : rep(a.size())) s[i + 1] += s[i];
    }
    // [L, R)
    S sum(int L, int R) { return s[R] - s[L]; }
};
#line 3 "cp-library/src/utility/heap.hpp"

template < class T > using heap_min = std::priority_queue< T, std::vector< T >, std::greater< T > >;
template < class T > using heap_max = std::priority_queue< T, std::vector< T >, std::less< T > >;

#line 27 "cp-library/src/cp-template.hpp"

#line 1 "cp-library/src/algorithm/bin_search.hpp"
template < class T, class F >
T bin_search(T ok, T ng, F f) {
    while(abs(ng - ok) > 1) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}

template < class T, class F >
T bin_search_real(T ok, T ng, F f, int step = 80) {
    while(step--) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}
#line 2 "cp-library/src/algorithm/argsort.hpp"

template < class T > std::vector< int > argsort(const std::vector< T > &a) {
    std::vector< int > ids((int)a.size());
    std::iota(ids.begin(), ids.end(), 0);
    std::sort(ids.begin(), ids.end(), [&](int i, int j) {
        return a[i] < a[j] || (a[i] == a[j] && i < j);
    });
    return ids;
}
#line 1 "macro.hpp"
namespace macro {

using size_type = int;
template < class container > void  sort(container& a) { std::sort(std:: begin(a), std:: end(a)); }
template < class container > void rsort(container& a) { std::sort(std::rbegin(a), std::rend(a)); }
template < class container > void reverse(container& a) { std::reverse(std::begin(a), std::end(a)); }
template < class container > void unique(container& a) {
    std::sort(std::begin(a), std::end(a));
    a.erase(std::unique(std::begin(a), std::end(a)), std::end(a));
}
template < class container > container  sorted(const container& a) { container b = a;  sort(b); return std::move(b); }
template < class container > container rsorted(const container& a) { container b = a; rsort(b); return std::move(b); }
template < class container, class compare > void sort(container& a, const compare& cmp) { std::sort(std::begin(a), std::end(a), cmp); }
template < class container, class compare > container sorted(const container& a, const compare& cmp) { container b = a; sort(b, cmp); return std::move(b); }
template < class container, class value > size_type lower_bound(const container& a, const value& x) { return std::lower_bound(std::begin(a), std::end(a), x) - std::begin(a); }
template < class container, class value > size_type upper_bound(const container& a, const value& x) { return std::upper_bound(std::begin(a), std::end(a), x) - std::begin(a); }

const std::vector<std::pair<size_type, size_type>> dir4 = { {+1,  0}, {-1,  0}, { 0, +1}, { 0, -1} };
const std::vector<std::pair<size_type, size_type>> dir8 = { {-1, -1}, {-1,  0}, {-1, +1}, { 0, -1}, { 0, +1}, {+1, -1}, {+1,  0}, {+1, +1} };

#ifdef _DEBUG
#define debug(x) std::cout << "[" << __LINE__ << "] " << #x << ": " << x << std::endl
#else
#define debug(x)
#endif

template < class container > void concat(container& a, const container& b) {
    a.insert(std::end(a), std::begin(b), std::end(b));
}
std::vector<size_type> iota(const size_type n) {
    std::vector<size_type> I(n);
    std::iota(std::begin(I), std::end(I), 0);
    return I;
}
template < class container > std::vector<size_type> sort_idx(const container& a) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return a[i] < a[j] or (a[i] == a[j] and i < j); });
    return I;
}
template < class container, class compare > std::vector<size_type> sort_idx(const container& a, const compare& cmp) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return cmp(a[i], a[j]) or (a[i] == a[j] and i < j); });
    return std::move(I);
}

struct grid {
    using size_type = int;
    size_type H, W;
    grid(const size_type H, const size_type W) : H(H), W(W) {}
    bool contains(const size_type i, const size_type j) {
        return 0 <= i and i < H and 0 <= j and j < W;
    }
};

using f64 = long double;

template < class T > vector< T >& operator++(vector< T >& a) { for(T& x : a) x++; return a; }
template < class T > vector< T >& operator--(vector< T >& a) { for(T& x : a) x--; return a; }
template < class T > vector< T >  operator++(vector< T >& a, signed) { vector< T > res = a; for(T& x : a) x++; return res; }
template < class T > vector< T >  operator--(vector< T >& a, signed) { vector< T > res = a; for(T& x : a) x--; return res; }

} // namespace macro

using namespace macro;
#line 1 "cp-library/src/data_structure/union_find.hpp"
class union_find {
  public:
    union_find(int n) : data(n, -1) {}
    int unite(int x, int y) {
        x = root(x), y = root(y);
        if(x != y) {
            if(size(x) < size(y)) swap(x, y);
            data[x] += data[y];
            return data[y] = x;
        }
        return -1;
    }
    int root(int x) { return data[x] < 0 ? x : data[x] = root(data[x]); }
    int size(int x) { return -data[root(x)]; }
    bool same(int x, int y) { return root(x) == root(y); }

  private:
    vector<int> data;
};
#line 2 "cp-library/src/number/modint.hpp"
struct modinfo { uint mod, root, isprime; };
template < modinfo const &ref >
struct modint {
    static constexpr uint const &mod = ref.mod;
    static constexpr uint const &root = ref.root;
    static constexpr uint const &isprime = ref.isprime;
    uint v = 0;
    constexpr modint& s(uint v) { this->v = v < mod ? v : v - mod; return *this; }
    constexpr modint(ll v = 0) { s(v % mod + mod); }
    modint operator-() const { return modint() - *this; }
    modint& operator+=(const modint& rhs) { return s(v + rhs.v); }
    modint& operator-=(const modint& rhs) { return s(v + mod - rhs.v); }
    modint& operator*=(const modint& rhs) { v = ull(v) * rhs.v % mod; return *this; }
    modint& operator/=(const modint& rhs) { return *this *= inv(rhs); }
    modint operator+(const modint& rhs) const { return modint(*this) += rhs; }
    modint operator-(const modint& rhs) const { return modint(*this) -= rhs; }
    modint operator*(const modint& rhs) const { return modint(*this) *= rhs; }
    modint operator/(const modint& rhs) const { return modint(*this) /= rhs; }
    friend modint pow(modint x, ll n) { modint res(1); while(n > 0) { if(n & 1) res *= x; x *= x; n >>= 1; } return res; }
    friend modint inv(modint v) {
        if(isprime) {
            return pow(v, mod - 2);
        } else {
            ll a = v.v, b = modint::mod, x = 1, y = 0, t;
            while(b > 0) { t = a / b; swap(a -= t * b, b); swap(x -= t * y, y); }
            return modint(x);
        }
    }
    friend modint operator+(int x, const modint& y) { return modint(x) + y; }
    friend modint operator-(int x, const modint& y) { return modint(x) - y; }
    friend modint operator*(int x, const modint& y) { return modint(x) * y; }
    friend modint operator/(int x, const modint& y) { return modint(x) / y; }
    friend istream& operator>>(istream& is, modint& m) { ll x; is >> x; m = modint(x); return is; }
    friend ostream& operator<<(ostream& os, const modint& m) { return os << m.v; }
    bool operator==(const modint& r) const { return v == r.v; }
    bool operator!=(const modint& r) const { return v != r.v; }
    static uint get_mod() { return mod; }
    static int is_prime() { return isprime; }
};
constexpr modinfo base998244353 { 998244353, 3, 1 };
constexpr modinfo base1000000007 { 1000000007, 0, 1 };
using mint998244353 = modint< base998244353 >;
using mint1000000007 = modint< base1000000007 >;
#line 5 "A.cpp"
using mint = mint1000000007;

mint solve(int N, int M) {
    if(M == 0) return pow(mint(2), N);
    union_find uf(N);
    for(int i : rep(M)) {
        int u = in(), v = in(); u--, v--;
        uf.unite(u, v);
    }
    int sz = 0;
    for(int i : rep(N)) sz += (uf.root(i) == i);
    return pow(mint(2), sz) + 1;
}

int main() {
    while(true) {
        int N = in(), M = in();
        if(make_pair(N, M) == make_pair(0, 0)) return 0;
        print(solve(N, M));
    }
}
accuracy: 1
time_ms: 40
memory_kb: 3532
final_rank: 1

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

struct UnionFind{
    vector<int> par; int n;
    UnionFind(){}
    UnionFind(int _n):par(_n,-1),n(_n){}
    int root(int x){return par[x]<0?x:par[x]=root(par[x]);}
    bool same(int x,int y){return root(x)==root(y);}
    int size(int x){return -par[root(x)];}
    bool unite(int x,int y){
        x=root(x),y=root(y); if(x==y)return false;
        if(size(x)>size(y))swap(x,y);
        par[y]+=par[x]; par[x]=y; n--; return true;
    }
};

/**
 * @brief Union Find
 */

int main() {
while(1) {
    int N, M;
    cin >> N >> M;
    if (N == 0) return 0;
    UnionFind UF(N);
    int Cur = N;
    rep(i,0,M) {
        int A, B;
        cin >> A >> B;
        A--, B--;
        if (UF.unite(A,B)) Cur--;
    }
    ll ANS = 1;
    rep(i,0,Cur) {
        ANS *= 2;
        ANS %= 1000000007;
    }
    if (Cur != N) ANS++;
    cout << ANS << endl;
}
}
accuracy: 1
time_ms: 130
memory_kb: 3704
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;

class UnionFind {
    public:
    vector<int> par;

    void init(int sz) {
        par.resize(sz, -1);
    }

    int root(int pos) {
        if (par[pos] == -1) return pos;
        par[pos] = root(par[pos]);
        return par[pos];
    }

    void unite(int u, int v) {
        u = root(u);
        v = root(v);
        if (u == v) return;
        par[u] = v;
    }

    bool same(int u, int v) {
        if (root(u) == root(v)) return true;
        return false;
    }
};

const int mod = 1000000007;
int N;
int M, A[1 << 19], B[1 << 19];

int main() {
    while (true) {
        // Step 1. Input
        cin >> N >> M; if (N + M == 0) break;
        for (int i = 1; i <= M; i++) cin >> A[i] >> B[i];
        
        // Step 2. Union Find
        int Answer = 1, Cnt = N;
        UnionFind UF; UF.init(N + 2);
        for (int i = 1; i <= M; i++) {
            if (UF.same(A[i], B[i]) == true) continue;
            Cnt -= 1;
            UF.unite(A[i], B[i]);
        }
        for (int i = 1; i <= Cnt; i++) Answer = (2 * Answer) % mod;

        // Step 3. Get Answer
        if (M >= 1) Answer = (Answer + 1) % mod;
        cout << Answer << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 130
memory_kb: 6136
final_rank: 16

code_snippet: #include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
#define maxn 100009
using namespace std;
const int MOD = 1e9 + 7;
int p[maxn];
long long bin[maxn];
int findset(int x) { return x == p[x] ? x : p[x] = findset(p[x]); }
void unionset(int x, int y) { p[findset(x)] = findset(y); }
int main() {
  int n, m, x, y;
  bin[0] = 1;
  for (int i = 1; i < maxn; i++)
    bin[i] = 2 * bin[i - 1] % MOD;
  while (scanf("%d%d", &n, &m) != EOF && n + m) {
    for (int i = 0; i <= n; i++)
      p[i] = i;
    for (int i = 0; i < m; i++) {
      scanf("%d%d", &x, &y);
      unionset(x, y);
    }
    int cnt = 0;
    for (int i = 1; i <= n; i++) {
      if (p[i] == i) {
        cnt++;
      }
    }
    int ans = bin[cnt];
    if (cnt != n)
      ans = (ans + 1) % MOD;
    printf("%d\n", ans);
  }
  return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 4324
final_rank: 11

code_snippet: #include <iostream>
using namespace std;
#define HH 100002
#define MOD 1000000007
int n, m;
int two[HH];
bool del[HH];
int ans;
int mod(int x) {
  while (x < 0)
    x += MOD;
  return x % MOD;
}
int parent[HH];
int find(int x) { return x == parent[x] ? x : parent[x] = find(parent[x]); }
void merge(int x, int y) {
  if (find(x) != find(y))
    parent[parent[x]] = parent[y];
}
void sol() {
  for (int i = 0; i <= n; i++)
    parent[i] = i;
  int iso = n;
  int hit = 0;
  for (int i = 0; i < m; i++) {
    int a, b;
    cin >> a >> b;
    if ((!del[a] || !del[b]) || (del[a] && del[b] && find(a) != find(b))) {
      iso--;
      merge(a, b);
    }
    del[a] = del[b] = true;
  }
  ans = two[iso] + (iso == n ? 0 : 1);
  ans = mod(ans);
  cout << ans << endl;
  for (int i = 0; i <= n; i++) {
    parent[i] = i;
    del[i] = false;
  }
}
int main() {
  two[0] = 1;
  for (int i = 1; i < HH; i++)
    two[i] = (two[i - 1] * 2) % MOD;
  while (cin >> n >> m && (n || m))
    sol();
}
accuracy: 1
time_ms: 170
memory_kb: 3936
final_rank: 15

code_snippet: #include <bits/stdc++.h>
#define GET_BIT(n, i) (((n) & (1 << ((i)-1))) >> ((i)-1))
#define SET_BIT(n, i) ((n) | (1 << ((i)-1)))
#define CLR_BIT(n, i) ((n) & ~(1 << ((i)-1)))
#define SHOW_A(x)                                                              \
  { cout << #x << " = " << x << endl; }
#define SHOW_B(x, y)                                                           \
  { cout << #x << " = " << x << ", " << #y << " = " << y << endl; }
#define SHOW_C(x, y, z)                                                        \
  {                                                                            \
    cout << #x << " = " << x << ", " << #y << " = " << y << ", " << #z         \
         << " = " << z << endl;                                                \
  }
#define REACH_HERE                                                             \
  { cout << "REACH_HERE! line: " << __LINE__ << endl; }
const double E = 1e-8;
const double PI = acos(-1);
using namespace std;
const int MAX_N = 100005, MAX_M = 10005;
const int MOD_BASE = 1000000007;
int baba[MAX_N];
int power_modulo(int n, int p, int M) {
  int result = 1;
  while (p > 0) {
    if (p % 2 == 1)
      result = ((long long)result * n) % M;
    p /= 2;
    n = ((long long)n * n) % M;
  }
  return result;
}
int find_baba(int i) {
  if (baba[i] != i) {
    int new_baba = find_baba(baba[i]);
    baba[i] = new_baba;
    return new_baba;
  }
  return i;
}
void solve(int n, int m) {
  for (int i = 1; i <= n; i++) {
    baba[i] = i;
  }
  bool unstable = false;
  int total = 0;
  for (int i = 0; i < m; i++) {
    int a, b;
    cin >> a >> b;
    baba[find_baba(b)] = find_baba(a);
    unstable = true;
  }
  int group = 0;
  for (int i = 1; i <= n; i++) {
    if (find_baba(i) == i) {
      group++;
    }
  }
  int ans = unstable ? 1 : 0;
  ans += power_modulo(2, group, MOD_BASE);
  cout << ans << endl;
}
int main() {
  ios::sync_with_stdio(false);
  while (true) {
    int n, m;
    cin >> n >> m;
    if (n == 0 && m == 0)
      break;
    solve(n, m);
  }
  return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 3520
final_rank: 8

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, n) for (int i = 0; i < (n); ++i)
#define rrep(i, n) for (int i = (n) - 1; i >= 0; --i)

#define all(c) std::begin(c), std::end(c)

#ifdef LOCAL
#define debug(...) debug_impl(#__VA_ARGS__, __VA_ARGS__)
template <class T, class ...Args> void debug_impl(string s, T&& f, Args &&...args) {
    cerr << "(" << s << "): " << "(" << forward<T>(f);
    ((cerr << ", " << forward<Args>(args)), ..., (cerr << ")\n"));
}
#else
#define debug(...) void(0)
#endif

template <class T> bool chmax(T& a, const T& b) { return b > a ? (a = b, true) : false; }
template <class T> bool chmin(T& a, const T& b) { return b < a ? (a = b, true) : false; }


template <class T> istream& operator>>(istream& in, vector<T>& v) {
    for (auto& e : v) in >> e;
    return in;
}
template <class ...Args> void read(Args&... args) {
    (cin >> ... >> args);
}

template <class T> ostream& operator<<(ostream& out, const vector<T>& v) {
    int n = v.size();
    rep(i, n) {
        out << v[i];
        if (i + 1 != n) out << ' ';
    }
    return out;
}

template <class T, class ...Tails> void print(T&& h, Tails &&... tails) {
    cout << h, ((cout << ' ' << forward<Tails>(tails)), ..., (cout << '\n'));
}

constexpr int mod = 1000000007;

int main() {

    while (true) {
        int n, m;
        read(n, m);

        if (n == 0 and m == 0) break;

        vector<vector<int>> g(n);
        rep(i, m) {
            int u, v;
            read(u, v);
            --u, --v;
            g[u].push_back(v);
            g[v].push_back(u);
        }

        vector<int8_t> vis(n);


        int cnum = 0;
        rep(i, n) if (not vis[i]) {
            ++cnum;

            vis[i] = true;
            deque<int> dq{ i };

            while (dq.size()) {
                int u = dq.front();
                dq.pop_front();

                for (int v : g[u]) if (not vis[v]) {
                    vis[v] = true;
                    dq.push_back(v);
                }
            }
        }

        long long ans = 1;
        rep(i, cnum) {
            ans = (ans + ans) % mod;
        }
        if (cnum != n) ++ans;

        ans %= mod;

        print(ans);
    }


    return 0;
}
accuracy: 1
time_ms: 220
memory_kb: 10352
final_rank: 20

code_snippet: #include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
#define _GLIBCXX_DEBUG
using namespace std;
using std::cout;
using std::cin;
using std::endl;
using ll=long long;
using ld=long double;
ll ILL=1167167167167167167;
const int INF=2100000000;
const ll mod=1e9+7;
#define rep(i,a) for (int i=0;i<a;i++)
#define all(p) p.begin(),p.end()
template<class T> using _pq = priority_queue<T, vector<T>, greater<T>>;
template<class T> ll LB(vector<T> &v,T a){return lower_bound(v.begin(),v.end(),a)-v.begin();}
template<class T> ll UB(vector<T> &v,T a){return upper_bound(v.begin(),v.end(),a)-v.begin();}
template<class T> bool chmin(T &a,const T &b){if(a>b){a=b;return 1;}else return 0;}
template<class T> bool chmax(T &a,const T &b){if(a<b){a=b;return 1;}else return 0;}
template<class T> void So(vector<T> &v) {sort(v.begin(),v.end());}
template<class T> void Sore(vector<T> &v) {sort(v.begin(),v.end(),[](T x,T y){return x>y;});}
void yneos(bool a){if(a) cout<<"Yes\n"; else cout<<"No\n";}
template<class T> void vec_out(vector<T> &p){for(int i=0;i<(int)(p.size());i++){if(i) cout<<" ";cout<<p[i];}cout<<"\n";}
namespace po167{
struct UFtree
{
	std::vector<int> wei;
	std::vector<int> q;
	int component;
	UFtree(int n):wei(n),component(n),par(n){
		for(int i=0;i<n;i++){
			wei[i]=1,par[i]=i;
		}
	}
	void intialize(){
		for(auto x:q){
			wei[root(x)]=1;
			par[x]=x;
		}
		component=(int)par.size();
		q={};
	}
	//根っこを返す
	int root(int a){
		if(a==par[a]) return a;
		return par[a]=root(par[a]);
	}
	//trueなら1,falseなら0
	int same(int a,int b){
		if(root(a)==root(b)) return 1;
		else return 0;
	}
	//a,bが違う根っこの元なら結合する,結合したらtrueを返す
	bool unite(int a,int b){
		a=root(a),b=root(b);
		if(a==b) return false;
		if(wei[a]<wei[b]) std::swap(a,b);
		par[b]=a;
		q.push_back(b);
		wei[a]+=wei[b];
		component--;
		return true;
	}
	private:
	std::vector<int> par;
};
}
using po167::UFtree;

ll my_pow(ll a,ll b){
	ll ans=1;
	while(b){
		if(b&1) ans=(ans*a)%mod;
		b>>=1;
		a=(a*a)%mod;
	}
	return ans;
}

int N,M;

void solve();
// oddloop
int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	while(cin>>N>>M,N) solve();
}

void solve(){
	if(M==0){
		cout<<my_pow(2,N)<<"\n";
		return ;
	}
	UFtree T(N);
	rep(i,M){
		int a,b;
		cin>>a>>b;
		T.unite(a-1,b-1);
	}
	cout<<(1+my_pow(2,T.component))%mod<<"\n";
}
accuracy: 1
time_ms: 40
memory_kb: 4596
final_rank: 9

code_snippet: #include <cstdio>
#include <vector>
#include <functional>
using namespace std;

const int mod = 1e9 + 7;

int power(int a, int b) {
  int res = 1;
  while (b) {
    if (b & 1) res = res * 1ll * a % mod;
    a = a * 1ll * a % mod;
    b /= 2; 
  }
  return res;
}

int main() {
  int n, m;
while (scanf("%d%d", &n, &m) == 2) {
  if (!n && !m) break;
  vector<int> x(m), y(m);
  vector<int> p(n + 1);
  for (int i = 1; i <= n; i++) p[i] = i;
  
  function<int(int)> find = [&](int u) {
    if (p[u] == u) return p[u];
    return p[u] = find(p[u]);
  };
  vector<int> have(n + 1, 0);
  for (int i = 0; i < m; i++) {
    scanf("%d%d", &x[i], &y[i]);
    have[x[i]] = have[y[i]] = 1;
    int u = find(x[i]), v = find(y[i]);
    if (u != v) {
      p[u] = v; 
    }
  }
  vector<int> vis(n + 1, 0);
  int cnt = 0;
  for (int i = 0; i < m; i++) {
    int u = find(x[i]);
    if (!vis[u]) {
      vis[u] = 1;
      cnt++; 
    }
  }
  int left = 0;
  for (int i = 1; i <= n; i++) left += (have[i] == 0);
  int ans = cnt == 0 ? 0 : 1;
  if (ans < 0) ans += mod;
  int add = power(2, cnt) * 1ll * power(2, left) % mod;
  ans = (ans + add) % mod;
  printf("%d\n", ans);
}
  return 0; 
}
accuracy: 1
time_ms: 60
memory_kb: 4552
final_rank: 13

code_snippet: #include<bits/stdc++.h>
#define rep(i,a,...) for(int i = (a)*(strlen(#__VA_ARGS__)!=0);i<(int)(strlen(#__VA_ARGS__)?__VA_ARGS__:(a));++i)
#define per(i,a,...) for(int i = (strlen(#__VA_ARGS__)?__VA_ARGS__:(a))-1;i>=(int)(strlen(#__VA_ARGS__)?(a):0);--i)
#define foreach(i, n) for(auto &i:(n))
#define all(x) (x).begin(), (x).end()
#define bit(x) (1ll << (x))
#define lambda(RES_TYPE, ...) (function<RES_TYPE(__VA_ARGS__)>)[&](__VA_ARGS__) -> RES_TYPE
#define method(FUNC_NAME, RES_TYPE, ...) function<RES_TYPE(__VA_ARGS__)> FUNC_NAME = lambda(RES_TYPE, __VA_ARGS__)
using namespace std;
using ll = long long;
using pii = pair<int,int>;
using pll = pair<ll,ll>;
const ll MOD = (ll)1e9+7;
//const ll MOD = 998244353;
const int INF = (ll)1e9+7;
const ll INFLL = (ll)1e18;
template<class t>
using vvector = vector<vector<t>>;
template<class t>
using vvvector = vector<vector<vector<t>>>;
template<class t>
using priority_queuer = priority_queue<t, vector<t>, greater<t>>;
template<class t, class u> bool chmax(t &a, u b){if(a<b){a=b;return true;}return false;}
template<class t, class u> bool chmin(t &a, u b){if(a>b){a=b;return true;}return false;}
#ifdef DEBUG
#define debug(x) cout<<"LINE "<<__LINE__<<": "<<#x<<" = "<<x<<endl;
#else
#define debug(x) (void)0
#endif

namespace templates{
    ll modpow(ll x, ll b,ll mod=MOD){
        ll res = 1;
        while(b){
            if(b&1)res = res * x % mod;
            x = x * x % mod;
            b>>=1;
        }
        return res;
    }

    ll modinv(ll x){
        return modpow(x, MOD-2);
    }

    bool was_output = false;

    void print();
    template <class t> void print(const vector<t> &);
    template <class t, class u> void print(const pair<t, u> &);
    template <class t> void print(const t&);
    template <class Head, class... Tail> void print(const Head&, const Tail&...);

    template <class t> void println(const vector<vector<t>>&);
    template <class t> void println(const vector<t>&);
    template <class t> void println(const t&);
    template <class Head, class... Tail> void println(const Head&, const Tail&...);
    void println();
    void newline();

    void print(){
        return;
    }

    template <class t>
    void print(const vector<t>&x){
        for(const t&i:x)print(i);
    }
    template <class t, class u>
    void print(const pair<t,u>&p){
        print(p.first);
        print(p.second);
    }
    template <class t>
    void print(const t&x){
        if(was_output)cout<<" ";
        cout<<x;
        was_output = true;
    }
    template <class Head, class... Tail>
    void print(const Head&head,const Tail&...tail){
        print(head);
        print(tail...);
    }

    template<class t>
    void println(const vector<vector<t>>&x){
        for(vector<t> i:x)println(i);
    }
    template<class t>
    void println(const vector<t>&x){
        for(const t&i:x)print(i);
        println();
    }
    template <class t>
    void println(const t&x){
        print(x);
        println();
    }
    void println(){
        if(was_output){
            cout << endl;
            was_output = false;
        }
    }
    template <class Head, class... Tail>
    void println(const Head&head,const Tail&...tail){
        print(head);
        println(tail...);
    }

    void newline(){
        was_output = true;
        println();
    }

    template<class t>
    istream& operator>>(istream&is, vector<t>&x){
        for(auto &i:x)is >> i;
        return is;
    }

    template<class t, class u>
    istream& operator>>(istream&is, pair<t, u>&x){
        is >> x.first >> x.second;
        return is;
    }

    template<class t>
    ostream& operator<<(ostream&os, vector<t> &v){
        os << "{";
        for(t &i:v){
            os << i << ", ";
        }
        os << "}";
        return os;
    }

    template<class t = long long>
    t in(){
        t res; cin >> res; return res;
    }

    template<class t>
    vector<t> sorted(vector<t> line,function<bool(t,t)> comp=[](t a,t b){return a<b;}){
        sort(line.begin(),line.end(),comp);
        return line;
    }

    template<class t>
    vector<t> reversed(vector<t> line){
        reverse(line.begin(),line.end());
        return line;
    }
    string reversed(string str){
        reverse(str.begin(),str.end());
        return str;
    }

    long long gcd(long long a,long long b){
        while(b){
            a %= b;
            swap(a,b);
        }
        return a;
    }

    long long lcm(long long a,long long b){
        return a / gcd(a,b) * b;
    }

    class output_initializer{
    public:
        output_initializer(){
            ios::sync_with_stdio(false);
            cin.tie(nullptr);
            cout << setprecision(20);
        }
    };output_initializer OUTPUT_INITIALIZER_INSTANCE = output_initializer();
}

using namespace templates;

template<long long mod>
class modint{
	public:
		long long x;
		modint(long long a){x=a%mod;if(x<0)x+=mod;}
		modint(){x=0;}

		modint pow(long long a){
			modint res(1), b(x);
			while(a){
				if(a&1)res*=b;
				b*=b;
				a>>=1;
			}
			return res;
		}

		modint inv(){return pow(mod-2);}

		modint& operator+=(modint a){x=(x+a.x)%mod;return *this;}
		modint& operator-=(modint a){x=x-a.x;if(x<0)x+=mod;return *this;}
		modint& operator*=(modint a){x=x*a.x%mod;return *this;}
		modint& operator/=(modint a){x=x*a.inv().x%mod;return *this;}

		modint operator+(modint a){return modint(x)+=a;}
		modint operator-(modint a){return modint(x)-=a;}
		modint operator*(modint a){return modint(x)*=a;}
		modint operator/(modint a){return modint(x)/=a;}

		modint operator-(){return modint(x);}

		bool operator==(const modint a){return x == a.x;}
		bool operator<(const modint a){return x < a.x;}
		bool operator>(const modint a){return x > a.x;}
};

template<long long mod>
ostream& operator<<(ostream& os, const modint<mod>& a){
	os << a.x;
	return os;
}

using mint = modint<MOD>;

class union_find{
public:
	int n;
	vector<int> parent;
    vector<int> has;
	union_find(int _n):n(_n){
		parent.resize(n);
        has.assign(n,1);
		rep(i, n){
			parent[i]=i;
		}
	}

	int get_parent(int x){
		if(parent[x]==x)return x;
		return parent[x] = get_parent(parent[x]);
	}

	bool is_same(int a, int b){
		int ap = get_parent(a);
		int bp = get_parent(b);
		return ap == bp;
	}

	void merge(int a, int b){
		int ap = get_parent(a);
		int bp = get_parent(b);
		if(ap==bp)return;
        has[ap] += has[bp];
		parent[bp] = ap;
	}

    int get_has(int p){
        return has[get_parent(p)];
    }

};

mint func(int n,int m){
    union_find uf(n);
    rep(_,m){
        uf.merge(in()-1,in()-1);
    }
    mint res(1);
    vector<int> used(n,false);
    int cnt = 0;
    rep(i,n){
        int p = uf.get_parent(i);
        if(used[p])continue;
        used[p] = true;
        ++cnt;
    }
    if(cnt==n){
        return mint(2).pow(n);
    }
    res += mint(2).pow(cnt);
    return res;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    while(true){
        int n = in();
        int m = in();
        if(n==0)break;
        println(func(n,m));
    }
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 4284
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;

template <int mod>
class Modint {
    using mint = Modint;
    static_assert(mod > 0, "Modulus must be positive");

public:
    static constexpr int get_mod() noexcept { return mod; }

    constexpr Modint(long long y = 0) noexcept : x(y >= 0 ? y % mod : (y % mod + mod) % mod) {}

    constexpr int value() const noexcept { return x; }

    constexpr mint& operator+=(const mint& r) noexcept { if ((x += r.x) >= mod) x -= mod; return *this; }
    constexpr mint& operator-=(const mint& r) noexcept { if ((x += mod - r.x) >= mod) x -= mod; return *this; }
    constexpr mint& operator*=(const mint& r) noexcept { x = static_cast<int>(1LL * x * r.x % mod); return *this; }
    constexpr mint& operator/=(const mint& r) noexcept { *this *= r.inv(); return *this; }

    constexpr mint operator-() const noexcept { return mint(-x); }

    constexpr mint operator+(const mint& r) const noexcept { return mint(*this) += r; }
    constexpr mint operator-(const mint& r) const noexcept { return mint(*this) -= r; }
    constexpr mint operator*(const mint& r) const noexcept { return mint(*this) *= r; }
    constexpr mint operator/(const mint& r) const noexcept { return mint(*this) /= r; }

    constexpr bool operator==(const mint& r) const noexcept { return x == r.x; }
    constexpr bool operator!=(const mint& r) const noexcept { return x != r.x; }

    constexpr mint inv() const noexcept {
        int a = x, b = mod, u = 1, v = 0;
        while (b > 0) {
            int t = a / b;
            std::swap(a -= t * b, b);
            std::swap(u -= t * v, v);
        }
        return mint(u);
    }

    constexpr mint pow(long long n) const noexcept {
        mint ret(1), mul(x);
        while (n > 0) {
            if (n & 1) ret *= mul;
            mul *= mul;
            n >>= 1;
        }
        return ret;
    }

    friend std::ostream& operator<<(std::ostream& os, const mint& r) {
        return os << r.x;
    }

    friend std::istream& operator>>(std::istream& is, mint& r) {
        long long t;
        is >> t;
        r = mint(t);
        return is;
    }

private:
    int x;
};

using mint = Modint<(int) 1e9 + 7>;

class UnionFind {
public:
    UnionFind() = default;
    explicit UnionFind(int n) : data(n, -1) {}

    int find(int x) {
        if (data[x] < 0) return x;
        return data[x] = find(data[x]);
    }

    void unite(int x, int y) {
        x = find(x);
        y = find(y);
        if (x == y) return;
        if (data[x] > data[y]) std::swap(x, y);
        data[x] += data[y];
        data[y] = x;
    }

    bool same(int x, int y) {
        return find(x) == find(y);
    }

    int size(int x) {
        return -data[find(x)];
    }

private:
    std::vector<int> data;
};

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(15);


    while (true) {
        int N, M;
        cin >> N >> M;
        if (N == 0 && M == 0) break;
        UnionFind uf(N);
        for (int i = 0; i < M; ++i) {
            int a, b;
            cin >> a >> b;
            --a, --b;
            uf.unite(a, b);
        }
        set<int> r;
        for (int i = 0; i < N; ++i) {
            r.insert(uf.find(i));
        }
        mint ans = mint(2).pow(r.size());
        if (r.size() < N) ans += 1;
        cout << ans << "\n";
    }
}
accuracy: 1
time_ms: 250
memory_kb: 8448
final_rank: 19

code_snippet: #line 1 "a.cpp"
#include <iostream>
#include <algorithm>
#include <utility>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <queue>
#include <map>
#include <math.h>
#include <string.h>
#include <iomanip>
#include <numeric>
#include <cstdlib>
#include <cstdint>
#include <cmath>
#include <functional>
#include <limits>
#include <cassert>
#include <bitset>
#include <chrono>
#include <random>
#include <memory>
 
/* macro */
 
#define rep(i, a, n) for (int i = (int)(a); i < (int)(n); i++)
#define rrep(i, a, n) for (int i = ((int)(n-1)); i >= (int)(a); i--)
#define Rep(i, a, n) for (i64 i = (i64)(a); i< (i64)(n); i++)
#define RRep(i, a, n) for (i64 i = ((i64)(n-i64(1))); i>=(i64)(a); i--)
#define all(v) (v).begin(),(v).end()
#define rall(v) (v).rbegin(),(v).rend()
#define Bit(n) (1LL<<(n))
 
/* macro end */
 
/* template */
 
namespace ebi {
 
#ifdef LOCAL
#define debug(...)                                                    \
    std::cerr << "LINE: " << __LINE__ << "  [" << #__VA_ARGS__ << "]:", \
        debug_out(__VA_ARGS__)
#else
#define debug(...)
#endif
 
void debug_out() { std::cerr << std::endl; }
 
template <typename Head, typename... Tail>
void debug_out(Head h, Tail... t) {
    std::cerr << " " << h;
    if (sizeof...(t) > 0) std::cout << " :";
    debug_out(t...);
}
 
template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, std::pair<T1, T2> pa) {
    return os << pa.first << " " << pa.second;
}
 
template <typename T>
std::ostream& operator<<(std::ostream& os, std::vector<T> vec) {
    for (std::size_t i = 0; i < vec.size(); i++) os << vec[i] << (i + 1 == vec.size() ? "" : " ");
    return os;
}
 
using size_t = std::size_t;
using i64 = long long;
using u64 = unsigned long long;
 
template<class T> void fill(std::vector<T> &v) { for(T &e: v) std::cin >> e; }
 
template <class T>
inline bool chmin(T &a, T b) {
    if (a > b){
        a = b;
        return true;
    }
    return false;
}
 
template <class T>
inline bool chmax(T &a, T b) {
    if (a < b){
        a = b;
        return true;
    }
    return false;
}
 
template <class T>
T gcd(T a, T b){
    if( b==0 ) return a;
    else return gcd(b, a%b);
}
 
template <class T>
T lcm(T a, T b) {
    return (a*b)/gcd(a,b);
}
 
template<class T>
T Pow(T x, i64 n) {
    T res = 1;
    while(n>0){
        if(n&1) res = res *x;
        x = x*x;
        n>>=1;
    }
    return res;
}
 
template<class T>
T scan() {
    T val;
    std::cin >> val;
    return val;
}
 
constexpr i64 LNF = std::numeric_limits<i64>::max()/4;
 
constexpr int INF = std::numeric_limits<int>::max()/4;
 
const long double PI = acos(-1);
 
const std::vector<int> dy = {1,0,-1,0,1,1,-1,-1};
const std::vector<int> dx = {0,1,0,-1,1,-1,1,-1};
 
}
 
/* template end */

#line 2 "utility/modint.hpp"

/*
    author: noshi91
    reference: https://noshi91.hatenablog.com/entry/2019/03/31/174006
    noshi91のブログで公開されているmodintを元にinv(), pow()を追加したものです
*/

#line 11 "utility/modint.hpp"

namespace ebi {

template<std::uint_fast64_t Modulus>
class modint {
  using u64 = std::uint_fast64_t;

public:
    u64 a;

    constexpr modint(const u64 x = 0) noexcept : a(x % Modulus) {}
    constexpr u64 &value() noexcept { return a; }
    constexpr u64 &val() noexcept { return a; }
    constexpr const u64 &value() const noexcept { return a; }
    constexpr modint operator+(const modint rhs) const noexcept {
        return modint(*this) += rhs;
    }
    constexpr modint operator-(const modint rhs) const noexcept {
        return modint(*this) -= rhs;
    }
    constexpr modint operator*(const modint rhs) const noexcept {
        return modint(*this) *= rhs;
    }
    constexpr modint operator/(const modint rhs) const noexcept {
        return modint(*this) /= rhs;
    }
    constexpr modint &operator+=(const modint rhs) noexcept {
        a += rhs.a;
        if (a >= Modulus) {
            a -= Modulus;
        }
        return *this;
    }
    constexpr modint &operator-=(const modint rhs) noexcept {
        if (a < rhs.a) {
        a += Modulus;
        }
        a -= rhs.a;
        return *this;
    }
    constexpr modint &operator*=(const modint rhs) noexcept {
        a = a * rhs.a % Modulus;
        return *this;
    }
    constexpr modint &operator/=(modint rhs) noexcept {
        u64 exp = Modulus - 2;
        while (exp) {
        if (exp % 2) {
            *this *= rhs;
        }
        rhs *= rhs;
        exp /= 2;
        }
        return *this;
    }
    constexpr modint operator-() const { return modint() - *this; }
    bool operator==(const u64 rhs) {
        return a == rhs;
    }
    bool operator!=(const u64 rhs) {
        return a != rhs;
    }
    constexpr modint& operator++() {
        a++;
        if( a == mod() ) a = 0;
        return *this;
    }
    constexpr modint& operator--() {
        if( a == 0 ) a = mod();
        a--;
        return *this;
    }

    modint pow(u64 n) const noexcept {
        modint res = 1;
        modint x = a;
        while(n>0){
            if(n&1) res *= x;
            x *= x;
            n >>=1;
        }
        return res;
    }
    modint inv() const {
        return pow(Modulus-2);
    }

    static u64 mod() {
        return Modulus;
    }
};

using modint998244353 = modint<998244353>;
using modint1000000007 = modint<1000000007>;

template<std::uint_fast64_t Modulus>
std::ostream& operator<<(std::ostream& os, modint<Modulus> a){
    return os << a.val();
}

} // namespace ebi
#line 2 "data_structure/UnionFind.hpp"

#line 4 "data_structure/UnionFind.hpp"

namespace ebi {

struct UnionFind {
private:
    std::vector<int> par;

public:
    UnionFind(int n=0): par(n,-1){ }

    bool same(int x,int y){
        return leader(x)==leader(y);
    }

    bool merge(int x, int y){
        x = leader(x); y = leader(y);
        if(x==y) return false;
        if(par[x]>par[y]) std::swap(x,y);
        par[x]+=par[y];
        par[y] = x;
        return true;
    }

    int leader(int x){
        if(par[x]<0) return x;
        else return par[x] = leader(par[x]);
    }

    int size(int x){
        return -par[leader(x)];
    }

    int count_group(){
        int c = 0;
        for(int i = 0; i<par.size(); i++){
            if(par[i]<0) c++; 
        }
        return c;
    }
};

} // namespace ebi
#line 137 "a.cpp"

namespace ebi {

using ld = long double;

using mint = modint1000000007;

void main_() {
    int n,m;
    while(std::cin >> n >> m, !(n == 0 && m == 0)) {
        if(m == 0) {
            std::cout << mint(2).pow(n).val() << '\n';
            continue;
        }
        UnionFind uf(n);
        rep(i,0,m) {
            int u,v;
            std::cin >> u >> v;
            uf.merge(u-1, v-1);
        }
        mint ans = mint(2).pow(uf.count_group()) + 1;
        std::cout << ans.val() << '\n';
    }
}
 
}

 
int main() {
    std::cout << std::fixed << std::setprecision(15);
    std::cin.tie(nullptr);
    std::ios::sync_with_stdio(false);
    int t = 1;
    while(t--) {
        ebi::main_();
    }
    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 3616
final_rank: 2

code_snippet: #include <bits/stdc++.h>

#include <utility>

namespace atcoder {

namespace internal {

// @param m `1 <= m`
// @return x mod m
constexpr long long safe_mod(long long x, long long m) {
    x %= m;
    if (x < 0) x += m;
    return x;
}

// Fast modular multiplication by barrett reduction
// Reference: https://en.wikipedia.org/wiki/Barrett_reduction
// NOTE: reconsider after Ice Lake
struct barrett {
    unsigned int _m;
    unsigned long long im;

    // @param m `1 <= m < 2^31`
    barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}

    // @return m
    unsigned int umod() const { return _m; }

    // @param a `0 <= a < m`
    // @param b `0 <= b < m`
    // @return `a * b % m`
    unsigned int mul(unsigned int a, unsigned int b) const {
        // [1] m = 1
        // a = b = im = 0, so okay

        // [2] m >= 2
        // im = ceil(2^64 / m)
        // -> im * m = 2^64 + r (0 <= r < m)
        // let z = a*b = c*m + d (0 <= c, d < m)
        // a*b * im = (c*m + d) * im = c*(im*m) + d*im = c*2^64 + c*r + d*im
        // c*r + d*im < m * m + m * im < m * m + 2^64 + m <= 2^64 + m * (m + 1)
        // < 2^64 * 2
        // ((ab * im) >> 64) == c or c + 1
        unsigned long long z = a;
        z *= b;
#ifdef _MSC_VER
        unsigned long long x;
        _umul128(z, im, &x);
#else
        unsigned long long x =
            (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
        unsigned int v = (unsigned int)(z - x * _m);
        if (_m <= v) v += _m;
        return v;
    }
};

// @param n `0 <= n`
// @param m `1 <= m`
// @return `(x ** n) % m`
constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
    if (m == 1) return 0;
    unsigned int _m = (unsigned int)(m);
    unsigned long long r = 1;
    unsigned long long y = safe_mod(x, m);
    while (n) {
        if (n & 1) r = (r * y) % _m;
        y = (y * y) % _m;
        n >>= 1;
    }
    return r;
}

// Reference:
// M. Forisek and J. Jancina,
// Fast Primality Testing for Integers That Fit into a Machine Word
// @param n `0 <= n`
constexpr bool is_prime_constexpr(int n) {
    if (n <= 1) return false;
    if (n == 2 || n == 7 || n == 61) return true;
    if (n % 2 == 0) return false;
    long long d = n - 1;
    while (d % 2 == 0) d /= 2;
    constexpr long long bases[3] = {2, 7, 61};
    for (long long a : bases) {
        long long t = d;
        long long y = pow_mod_constexpr(a, t, n);
        while (t != n - 1 && y != 1 && y != n - 1) {
            y = y * y % n;
            t <<= 1;
        }
        if (y != n - 1 && t % 2 == 0) {
            return false;
        }
    }
    return true;
}
template <int n>
constexpr bool is_prime = is_prime_constexpr(n);

// @param b `1 <= b`
// @return pair(g, x) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
    a = safe_mod(a, b);
    if (a == 0) return {b, 0};

    // Contracts:
    // [1] s - m0 * a = 0 (mod b)
    // [2] t - m1 * a = 0 (mod b)
    // [3] s * |m1| + t * |m0| <= b
    long long s = b, t = a;
    long long m0 = 0, m1 = 1;

    while (t) {
        long long u = s / t;
        s -= t * u;
        m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b

        // [3]:
        // (s - t * u) * |m1| + t * |m0 - m1 * u|
        // <= s * |m1| - t * u * |m1| + t * (|m0| + |m1| * u)
        // = s * |m1| + t * |m0| <= b

        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    // by [3]: |m0| <= b/g
    // by g != b: |m0| < b/g
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}

// Compile time primitive root
// @param m must be prime
// @return primitive root (and minimum in now)
constexpr int primitive_root_constexpr(int m) {
    if (m == 2) return 1;
    if (m == 167772161) return 3;
    if (m == 469762049) return 3;
    if (m == 754974721) return 11;
    if (m == 998244353) return 3;
    int divs[20] = {};
    divs[0] = 2;
    int cnt = 1;
    int x = (m - 1) / 2;
    while (x % 2 == 0) x /= 2;
    for (int i = 3; (long long)(i)*i <= x; i += 2) {
        if (x % i == 0) {
            divs[cnt++] = i;
            while (x % i == 0) {
                x /= i;
            }
        }
    }
    if (x > 1) {
        divs[cnt++] = x;
    }
    for (int g = 2;; g++) {
        bool ok = true;
        for (int i = 0; i < cnt; i++) {
            if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                ok = false;
                break;
            }
        }
        if (ok) return g;
    }
}
template <int m>
constexpr int primitive_root = primitive_root_constexpr(m);

}  // namespace internal

}  // namespace atcoder

#include <cassert>
#include <numeric>
#include <type_traits>

namespace atcoder {

namespace internal {

#ifndef _MSC_VER
template <class T>
using is_signed_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value ||
                                  std::is_same<T, __int128>::value,
                              std::true_type, std::false_type>::type;

template <class T>
using is_unsigned_int128 =
    typename std::conditional<std::is_same<T, __uint128_t>::value ||
                                  std::is_same<T, unsigned __int128>::value,
                              std::true_type, std::false_type>::type;

template <class T>
using make_unsigned_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value, __uint128_t,
                              unsigned __int128>;

template <class T>
using is_integral =
    typename std::conditional<std::is_integral<T>::value ||
                                  is_signed_int128<T>::value ||
                                  is_unsigned_int128<T>::value,
                              std::true_type, std::false_type>::type;

template <class T>
using is_signed_int =
    typename std::conditional<(is_integral<T>::value &&
                               std::is_signed<T>::value) ||
                                  is_signed_int128<T>::value,
                              std::true_type, std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<(is_integral<T>::value &&
                               std::is_unsigned<T>::value) ||
                                  is_unsigned_int128<T>::value,
                              std::true_type, std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<
    is_signed_int128<T>::value, make_unsigned_int128<T>,
    typename std::conditional<std::is_signed<T>::value, std::make_unsigned<T>,
                              std::common_type<T>>::type>::type;

#else

template <class T>
using is_integral = typename std::is_integral<T>;

template <class T>
using is_signed_int =
    typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
                              std::true_type, std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<is_integral<T>::value &&
                                  std::is_unsigned<T>::value,
                              std::true_type, std::false_type>::type;

template <class T>
using to_unsigned =
    typename std::conditional<is_signed_int<T>::value, std::make_unsigned<T>,
                              std::common_type<T>>::type;

#endif

template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;

template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;

template <class T>
using to_unsigned_t = typename to_unsigned<T>::type;

}  // namespace internal

}  // namespace atcoder

#include <cassert>
#include <numeric>
#include <type_traits>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

struct modint_base {};
struct static_modint_base : modint_base {};

template <class T>
using is_modint = std::is_base_of<modint_base, T>;
template <class T>
using is_modint_t = std::enable_if_t<is_modint<T>::value>;

}  // namespace internal

template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : internal::static_modint_base {
    using mint = static_modint;

   public:
    static constexpr int mod() { return m; }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    static_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    static_modint(T v) {
        long long x = (long long)(v % (long long)(umod()));
        if (x < 0) x += umod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    static_modint(T v) {
        _v = (unsigned int)(v % umod());
    }
    static_modint(bool v) { _v = ((unsigned int)(v) % umod()); }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v -= rhs._v;
        if (_v >= umod()) _v += umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        unsigned long long z = _v;
        z *= rhs._v;
        _v = (unsigned int)(z % umod());
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        if (prime) {
            assert(_v);
            return pow(umod() - 2);
        } else {
            auto eg = internal::inv_gcd(_v, m);
            assert(eg.first == 1);
            return eg.second;
        }
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

   private:
    unsigned int _v;
    static constexpr unsigned int umod() { return m; }
    static constexpr bool prime = internal::is_prime<m>;
};

template <int id>
struct dynamic_modint : internal::modint_base {
    using mint = dynamic_modint;

   public:
    static int mod() { return (int)(bt.umod()); }
    static void set_mod(int m) {
        assert(1 <= m);
        bt = internal::barrett(m);
    }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    dynamic_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        long long x = (long long)(v % (long long)(mod()));
        if (x < 0) x += mod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        _v = (unsigned int)(v % mod());
    }
    dynamic_modint(bool v) { _v = ((unsigned int)(v) % mod()); }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v += mod() - rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        _v = bt.mul(_v, rhs._v);
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        auto eg = internal::inv_gcd(_v, mod());
        assert(eg.first == 1);
        return eg.second;
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

   private:
    unsigned int _v;
    static internal::barrett bt;
    static unsigned int umod() { return bt.umod(); }
};
template <int id>
internal::barrett dynamic_modint<id>::bt = 998244353;

using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;

namespace internal {

template <class T>
using is_static_modint = std::is_base_of<internal::static_modint_base, T>;

template <class T>
using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;

template <class>
struct is_dynamic_modint : public std::false_type {};
template <int id>
struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};

template <class T>
using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;

}  // namespace internal

}  // namespace atcoder

#define For(i, a, b) for (int i = (int)(a); i < (int)(b); ++i)
#define rFor(i, a, b) for (int i = (int)(a)-1; i >= (int)(b); --i)
#define rep(i, n) For(i, 0, (n))
#define rrep(i, n) rFor(i, (n), 0)
#define fi first
#define se second

using namespace std;

typedef long long lint;
typedef unsigned long long ulint;
typedef pair<int, int> pii;
typedef pair<lint, lint> pll;

template <class T>
bool chmax(T& a, const T& b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}
template <class T>
bool chmin(T& a, const T& b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}

template <class T>
T div_floor(T a, T b) {
    if (b < 0) a *= -1, b *= -1;
    return a >= 0 ? a / b : (a + 1) / b - 1;
}
template <class T>
T div_ceil(T a, T b) {
    if (b < 0) a *= -1, b *= -1;
    return a > 0 ? (a - 1) / b + 1 : a / b;
}

template <typename T>
struct coord_comp {
    vector<T> v;
    bool sorted = false;

    coord_comp() {}

    int size() { return v.size(); }

    void add(T x) { v.push_back(x); }

    void build() {
        sort(v.begin(), v.end());
        v.erase(unique(v.begin(), v.end()), v.end());
        sorted = true;
    }

    int get_idx(T x) {
        assert(sorted);
        return lower_bound(v.begin(), v.end(), x) - v.begin();
    }

    T& operator[](int i) { return v[i]; }
};

constexpr lint mod = 1000000007;
constexpr lint INF = mod * mod;
constexpr int MAX = 100010;

using namespace atcoder;
using mint = modint1000000007;

typedef struct UnionFindTree {
    vector<int> par;

    UnionFindTree(int n) { par.resize(n, -1); }

    void clear() { fill(par.begin(), par.end(), -1); }

    bool is_root(int x) { return par[x] < 0; }

    int find(int x) {
        if (is_root(x)) return x;
        return par[x] = find(par[x]);
    }

    int size(int x) { return -par[find(x)]; }

    bool unite(int x, int y) {
        x = find(x);
        y = find(y);
        if (x == y) return false;
        if (size(x) < size(y)) swap(x, y);
        par[x] += par[y];
        par[y] = x;
        return true;
    }

    bool same(int x, int y) { return find(x) == find(y); }
} UF;

int main() {
    int n, m;
    while (scanf("%d%d", &n, &m) && n) {
        if (m == 0) {
            printf("%u\n", mint(2).pow(n).val());
            continue;
        }
        UF uf(n);
        int cnt = n;
        rep(i, m) {
            int a, b;
            scanf("%d%d", &a, &b);
            --a;
            --b;
            cnt -= uf.unite(a, b);
        }
        printf("%u\n", (mint(2).pow(cnt) + 1).val());
    }
}
accuracy: 1
time_ms: 40
memory_kb: 3640
final_rank: 3

code_snippet: #include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define Inf 100000000000000000

struct dsu {
	public:
	dsu() : _n(0) {}
	explicit dsu(int n) : _n(n), parent_or_size(n, -1) {}

	int merge(int a, int b) {
		assert(0 <= a && a < _n);
		assert(0 <= b && b < _n);
		int x = leader(a), y = leader(b);
		if (x == y) return x;
		if (-parent_or_size[x] < -parent_or_size[y]) std::swap(x, y);
		parent_or_size[x] += parent_or_size[y];
		parent_or_size[y] = x;
		return x;
	}

	bool same(int a, int b) {
		assert(0 <= a && a < _n);
		assert(0 <= b && b < _n);
		return leader(a) == leader(b);
	}

	int leader(int a) {
		assert(0 <= a && a < _n);
		if (parent_or_size[a] < 0) return a;
		return parent_or_size[a] = leader(parent_or_size[a]);
	}

	int size(int a) {
		assert(0 <= a && a < _n);
		return -parent_or_size[leader(a)];
	}

	std::vector<std::vector<int>> groups() {
		std::vector<int> leader_buf(_n), group_size(_n);
		for (int i = 0; i < _n; i++) {
			leader_buf[i] = leader(i);
			group_size[leader_buf[i]]++;
		}
		std::vector<std::vector<int>> result(_n);
		for (int i = 0; i < _n; i++) {
			result[i].reserve(group_size[i]);
		}
		for (int i = 0; i < _n; i++) {
			result[leader_buf[i]].push_back(i);
		}
		result.erase(
			std::remove_if(result.begin(), result.end(),
						   [&](const std::vector<int>& v) { return v.empty(); }),
			result.end());
		return result;
	}

	private:
	int _n;
	// root node: -1 * component size
	// otherwise: parent
	std::vector<int> parent_or_size;
};

template <std::uint_fast64_t Mod> class modint {
	using u64 = std::uint_fast64_t;

	public:
	u64 a;

	constexpr modint(const u64 x = 0) noexcept : a(x % Mod) {
		a = x%Mod;
		if(a<0)a += Mod;		
	}
	constexpr u64 &val() noexcept { return a; }
	constexpr const u64 &val() const noexcept { return a; }
	constexpr modint operator+(const modint rhs) const noexcept {
		return modint(*this) += rhs;
	}
	constexpr modint operator-(const modint rhs) const noexcept {
		return modint(*this) -= rhs;
	}
	constexpr modint operator*(const modint rhs) const noexcept {
		return modint(*this) *= rhs;
	}
	constexpr modint operator/(const modint rhs) const noexcept {
		return modint(*this) /= rhs;
	}
	constexpr modint &operator+=(const modint rhs) noexcept {
		a += rhs.a;
		if (a >= Mod) {
			a -= Mod;
		}
		return *this;
	}
	constexpr modint &operator-=(const modint rhs) noexcept {
		if (a < rhs.a) {
			a += Mod;
		}
		a -= rhs.a;
		return *this;
	}
	constexpr modint &operator*=(const modint rhs) noexcept {
		a = a * rhs.a % Mod;
		return *this;
	}
	constexpr modint &operator/=(modint rhs) noexcept {
		*this *= rhs.inv();
		return *this;
	}
	
	constexpr modint pow(long long n) const noexcept {
		modint x = *this;
		modint ret = 1;
		while (n) {
			if (n&1) {
				ret *= x;
			}
			x *= x;
			n >>= 1;
		}
		return ret;
	}
	
	constexpr modint inv() const noexcept {
		return pow(Mod-2);
	}
	
};

using mint = modint<1000000007>;

int main(){
	
	while(true){
		int N,M;
		cin>>N>>M;
		
		if(N==0)break;
		
		if(M==0){
			cout<<mint(2).pow(N).val()<<endl;
			continue;
		}
		
		dsu D(N);
		rep(i,M){
			int a,b;
			cin>>a>>b;
			D.merge(a-1,b-1);
		}
		
		auto ret = D.groups();
		mint ans = mint(2).pow(ret.size());
		ans+=1;
		
		cout<<ans.val()<<endl;
		
	}
	
	return 0;
}
accuracy: 1
time_ms: 170
memory_kb: 10496
final_rank: 18

code_snippet: #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}

constexpr ll mod=1e9+7;

ll mod_pow(ll a,ll b){
    a%=mod;
    if(b==0)return 1;
    if(b==1)return a;
    ll res=mod_pow(a,b/2)%mod;
    res*=res; res%=mod;
    if(b%2)res*=a;
    return res%mod;
}

struct UnionFind{
    vector<int> par,num;
    UnionFind(int n):par(n),num(n,1){
        iota(par.begin(),par.end(),0);  //include<numeric>
    }
    int find(int v){
        return (par[v]==v)?v:(par[v]=find(par[v]));
    }
    void unite(int u,int v){
        u=find(u),v=find(v);
        if(u==v)return;
        if(num[u]<num[v])swap(u,v);
        num[u]+=num[v];
        par[v]=u;
    }
    bool same(int u,int v){
        return find(u) == find(v);
    }
    int size(int v){
        return num[find(v)];
    }
};

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n,m;
    while(cin >> n >> m,n){
        if(m==0){
            printf("%lld\n",mod_pow(2,n));
        }
        else{
            UnionFind uf(n);
            for(int i=0;i<m;i++){
                int x,y; cin >> x >> y;
                x--; y--;
                uf.unite(x,y);
            }
            int cnt=0;
            for(int i=0;i<n;i++){
                if(uf.find(i)==i)cnt++;
            }
            printf("%lld\n",mod_pow(2,cnt)+1);
        }
    }
}
accuracy: 1
time_ms: 50
memory_kb: 3704
final_rank: 6

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define ALL(x) begin(x),end(x)
#define rep(i,n) for(int i=0;i<(n);i++)
#define debug(v) cout<<#v<<":";for(auto x:v){cout<<x<<' ';}cout<<endl;
#define mod 998244353
using ll=long long;
const int INF=1000000000;
const ll LINF=1001002003004005006ll;
int dx[]={1,0,-1,0},dy[]={0,1,0,-1};
template<class T>bool chmax(T &a,const T &b){if(a<b){a=b;return true;}return false;}
template<class T>bool chmin(T &a,const T &b){if(b<a){a=b;return true;}return false;}

struct IOSetup{
    IOSetup(){
        cin.tie(0);
        ios::sync_with_stdio(0);
        cout<<fixed<<setprecision(12);
    }
} iosetup;
 
template<typename T>
ostream &operator<<(ostream &os,const vector<T>&v){
    for(int i=0;i<(int)v.size();i++) os<<v[i]<<(i+1==(int)v.size()?"":" ");
    return os;
}
template<typename T>
istream &operator>>(istream &is,vector<T>&v){
    for(T &x:v)is>>x;
    return is;
}


template<ll Mod>
struct ModInt{
    long long x;
    ModInt():x(0){}
    ModInt(long long y):x(y>=0?y%Mod:(Mod-(-y)%Mod)%Mod){}
    ModInt &operator+=(const ModInt &p){
        if((x+=p.x)>=Mod) x-=Mod;
        return *this;
    }
    ModInt &operator-=(const ModInt &p){
        if((x+=Mod-p.x)>=Mod)x-=Mod;
        return *this;
    }
    ModInt &operator*=(const ModInt &p){
        x=(int)(1ll*x*p.x%Mod);
        return *this;
    }
    ModInt &operator/=(const ModInt &p){
        (*this)*=p.inverse();
        return *this;
    }
    ModInt operator-()const{return ModInt(-x);}
    ModInt operator+(const ModInt &p)const{return ModInt(*this)+=p;}
    ModInt operator-(const ModInt &p)const{return ModInt(*this)-=p;}
    ModInt operator*(const ModInt &p)const{return ModInt(*this)*=p;}
    ModInt operator/(const ModInt &p)const{return ModInt(*this)/=p;}
    bool operator==(const ModInt &p)const{return x==p.x;}
    bool operator!=(const ModInt &p)const{return x!=p.x;}
    ModInt inverse()const{
        int a=x,b=Mod,u=1,v=0,t;
        while(b>0){
            t=a/b;
            swap(a-=t*b,b);swap(u-=t*v,v);
        }
        return ModInt(u);
    }
    ModInt pow(long long n)const{
        ModInt ret(1),mul(x);
        while(n>0){
            if(n&1) ret*=mul;
            mul*=mul;n>>=1;
        }
        return ret;
    }
    friend ostream &operator<<(ostream &os,const ModInt &p){return os<<p.x;}
    friend istream &operator>>(istream &is,ModInt &a){long long t;is>>t;a=ModInt<Mod>(t);return (is);}
    static int get_mod(){return Mod;}
};

using mint=ModInt<1000000007>;

struct UnionFind{
    private:
    vector<int> par,siz;

    public:
    int con;
    UnionFind(int n):par(n),siz(n,1),con(n){
        iota(begin(par),end(par),0);
    }
    int root(int x){
        return (par[x]==x?x:(par[x]=root(par[x])));
    }
    bool sameroot(int x,int y){
        return root(x)==root(y);
    }
    bool unite(int x,int y){
        x=root(x);y=root(y);
        if(x==y) return false;
        if(siz[x]<siz[y])swap(x,y);
        siz[x]+=siz[y];
        par[y]=x;
        con--;
        return true;
    }
    int size(int x){
        return siz[root(x)];
    }
};

int n,m;

void solve(){
    UnionFind uf(n);
    rep(i,m){
        int u,v;cin>>u>>v;u--,v--;
        uf.unite(u,v);
    }
    if(uf.con<n) cout<<(mint(2).pow(uf.con)+1)<<endl;
    else         cout<<mint(2).pow(uf.con)<<endl;
}

signed main(){
    while(cin>>n>>m,n) solve();
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 3756
final_rank: 7

code_snippet: #include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
#include <utility>
#include <tuple>
#include <cmath>
#include <numeric>
#include <set>
#include <map>
#include <array>
#include <complex>
#include <iomanip>
#include <cassert>
#include <random>
#include <chrono>
using ll = long long;
using std::cin;
using std::cout;
using std::endl;
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
const int inf = (int)1e9 + 7;
const long long INF = 1LL << 60;

namespace KKT89
{
  struct UnionFind
  {
    std::vector<int> par;
    UnionFind(int n)
    {
        par.assign(n, -1);
    }
    int root(int a)
    {
        if (par[a] < 0)
        {
            return a;
        }
        return par[a] = root(par[a]);
    }

    int size(int a)
    {
        return -par[root(a)];
    }
    bool connect(int a, int b)
    {
        a = root(a);
        b = root(b);
        if (a == b)
        {
            return false;
        }
        if (size(a) < size(b))
        {
            std::swap(a, b);
        }

        par[a] += par[b];
        par[b] = a;

        return true;
    }
    bool same(int a, int b)
    {
        return root(a) == root(b);
    }
  };
}

constexpr int mod = (int)1e9 + 7;
template<int mod>
struct ModInt {
  int x;

  ModInt() : x(0) {}

  ModInt(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}

  ModInt &operator+=(const ModInt &p) {
    if((x += p.x) >= mod) x -= mod;
    return *this;
  }

  ModInt &operator-=(const ModInt &p) {
    if((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }

  ModInt &operator*=(const ModInt &p) {
    x = (int) (1LL * x * p.x % mod);
    return *this;
  }

  ModInt &operator/=(const ModInt &p) {
    *this *= p.inverse();
    return *this;
  }

  ModInt operator-() const { return ModInt(-x); }

  ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }

  ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }

  ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }

  ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }

  bool operator==(const ModInt &p) const { return x == p.x; }

  bool operator!=(const ModInt &p) const { return x != p.x; }

  ModInt inverse() const {
    int a = x, b = mod, u = 1, v = 0, t;
    while(b > 0) {
      t = a / b;
      std::swap(a -= t * b, b);
      std::swap(u -= t * v, v);
    }
    return ModInt(u);
  }

  ModInt pow(int64_t n) const {
    ModInt ret(1), mul(x);
    while(n > 0) {
      if(n & 1) ret *= mul;
      mul *= mul;
      n >>= 1;
    }
    return ret;
  }

  friend std::ostream &operator<<(std::ostream &os, const ModInt &p) {
    return os << p.x;
  }

  friend std::istream &operator>>(std::istream &is, ModInt &a) {
    int64_t t;
    is >> t;
    a = ModInt< mod >(t);
    return (is);
  }

  static int get_mod() { return mod; }
};

using mint = ModInt<mod>;

void solve()
{
	int n, m; cin >> n >> m;
	if(n == 0 and m == 0)
		exit(0);
	KKT89::UnionFind uf(n);
	for (int i = 0; i < m; ++i)
	{
		int u, v; cin >> u >> v;
		u -= 1;
		v -= 1;
		uf.connect(u, v);
	}

	int sz = 0;
	for (int i = 0; i < n; ++i)
	{
		if(i == uf.root(i))
			sz += 1;
	}
	mint res = mint(2).pow(sz) + (m > 0);
	cout << res << "\n";
}
int main()
{
  std::cin.tie(nullptr);
  std::ios::sync_with_stdio(false);


  int kkt = 89;
  //cin >> kkt;
  while(kkt)
  {
    solve();
  }
  return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 3768
final_rank: 4