#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<map>
#define _rep(i,a,b) for(int i=(a);i<=(b);i++)
#define _per(i,a,b) for(int i=(a);i>=(b);i--)
using namespace std;
typedef long long ll;
template<typename T1,typename T2>
inline bool cmin(T1 &x,T2 y){return x>y? x=y,1:0;}
template<typename T1,typename T2>
inline bool cmax(T1 &x,T2 y){return x<y? x=y,1:0;}
template<typename Tp>
inline void Rd(Tp &x){
	int ff=1;char ch=getchar();
	x=0;
	while(ch<'0' || ch>'9'){
		if(ch=='-') ff=-1;
		ch=getchar();
	}
	while('0'<=ch && ch<='9') x=x*10+ch-'0', ch=getchar();
	x=x*ff;
}
const int N=5e5+100,M=1e6+100,mod=1e9+7;
int n,m,_head[N],_to[M<<1],_nxt[M<<1],_cnt=1;
inline void _add(int u,int v){
	_to[++_cnt]=v;
	_nxt[_cnt]=_head[u];
	_head[u]=_cnt;
}

int low[N],dfn[N],now=0;
int bri[M<<1];
void Tarjan(int p,int in_edge){
	low[p]=dfn[p]=++now;
	for(int i=_head[p],y; i; i=_nxt[i])
		if(!dfn[y=_to[i]]){
			Tarjan(y,i);
			cmin(low[p],low[y]);
			if(low[y]>dfn[p]) bri[i]=bri[i^1]=true;
		}
		else if(i!=(in_edge^1)) cmin(low[p],dfn[y]);
}

bool vis[N];
int _id=0,nid[N],ecnt[N],pcnt[N];//计算边数和点数.
int head[N],to[N<<1],nxt[N<<1],cnt=1;//新图.
inline void add(int u,int v){
//	printf("add(%d,%d)\n",u,v);
	to[++cnt]=v;
	nxt[cnt]=head[u];
	head[u]=cnt;
}

void dfs(int p){
	vis[p]=true;
	nid[p]=_id;
	pcnt[_id]++;
	for(int i=_head[p],y; i; i=_nxt[i]){
		y=_to[i];
		if(!vis[y] && !bri[i]) dfs(y);
		if(bri[i] && vis[y]) add(nid[p],nid[y]),add(nid[y],nid[p]);//加入桥边.
		if(!bri[i]) ecnt[_id]+=(i&1);//&1防止重复加.
	}
}

inline ll qp(int ct){
	ll ans=1,t=2;
	for(;ct;ct>>=1){
		if(ct&1) ans=(ans*t)%mod;
		t=t*t%mod;
	}
	return ans;
}

ll f[N][3];//均无,不通,通.
int g[N],qz[N],hz[N],bx[N];
void DP(int p,int fa){
//	printf("p=%d\n",p);
	f[p][0]=f[p][2]=1,f[p][1]=0;
	int siz=0;
	for(int i=head[p],y;i;i=nxt[i])
		if((y=to[i])!=fa){
			DP(y,p);
			f[p][0]=(f[p][0]*f[y][0]*2)%mod;
			//f[y,0]不包括子修了p--y这条路的情况.
			f[p][2]=(f[p][2]*((f[y][0]*2+f[y][2])%mod))%mod;
			//子不通时路任意修,否则必修.
			g[++siz]=f[y][0];
			bx[siz]=f[y][2];
		}
	qz[0]=hz[siz+1]=1;
	_rep(i,1,siz) qz[i]=(qz[i-1]*g[i])%mod;
	_per(i,siz,1) hz[i]=(hz[i+1]*g[i])%mod;
	_rep(i,1,siz) f[p][1]=(f[p][1]+qz[i-1]*hz[i+1]%mod*bx[i])%mod;
	
	
//	printf("#%d f= %lld %lld %lld\n",p,f[p][0],f[p][1],f[p][2]);
	f[p][2]=((f[p][2]-f[p][0])%mod+mod)%mod;
	//容斥一下,就得到子至少有1个的情况.
	
	f[p][2]=(
		f[p][2]*qp(ecnt[p]+pcnt[p])%mod+//有子时自己随便.
		f[p][0]*qp(ecnt[p])%mod*(qp(pcnt[p])-1)%mod//无子时自己至少出1个军营.
		)%mod;
	f[p][0]=(f[p][0]*qp(ecnt[p]))%mod;
	
	f[p][1]=(f[p][1]*qp(ecnt[p]))%mod;
	
//	printf("#%d f= %lld %lld %lld\n",p,f[p][0],f[p][1],f[p][2]);
}

int main(){
	freopen("barrack4.in","r",stdin);
//	freopen("barrack.out","w",stdout);
	Rd(n),Rd(m);
	int u,v;
	_rep(i,1,m){
		Rd(u),Rd(v);
		_add(u,v),_add(v,u);
	}
	Tarjan(1,0);
//	_rep(i,2,_cnt)
//		if(bri[i]){
//			u=to[i],v=to[i^1];
//			if(u<v) printf("%d--%d bridge\n",u,v);
//		}
	_rep(i,1,n)
		if(!vis[i]) ++_id,dfs(i);
//	printf("Fine\n");
//	_rep(i,1,_id) printf("#%d E %d P %d\n",i,ecnt[i],pcnt[i]);
//	return 0;
	DP(1,0);
	printf("%lld\n",((f[1][1]+f[1][2])%mod+mod)%mod);
	return 0;
}
