#include <iostream>
#include <string>
#include <iomanip>
#include <fstream>
#include <vector>
#include <algorithm>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
using namespace std;

/*
int main()
{
	int n,m;
	cin>>n>>m;
	int x = min(n,m);
	if (x%2==1)
	{
		cout<<"Akshat"<<endl;
	}
	else cout<<"Malvika"<<endl;
}

int main()
{
	int n;
	cin>>n;
	vector<int> a(n);
	for (int i = 0; i < n; i++)
	{
		cin>>a[i];
	}
	int dec = 0;
	int inc = 0;
	bool in = false;
	bool de = false;
	int st = -1;
	int end = -1;
	int mx = -1;
	vector<int> in1;
	vector<int> in2;
	vector<int> dec;
	for (int i = 1; i < n; i++)
	{
		if (a[i] > a[i-1] && in)
		{
			continue;
		}
		else if (a[i] > a[i-1] && !in)
		{
			inc++;
			in = true;
			end = i;
			de = false;
		}
		else if (a[i] < a[i-1] && !de)
		{
			st = i;
			mx = a[i-1];
			dec++;
			in = false;
			de = true;
		}
	}
	if (de) end = n;

	if (inc <= 2 && dec <= 1)
	{
		if (dec == 1)
		{
			bool ok1,ok2;
			ok1 = false;
			ok2 = false;
			if (st > 1)
			{
				if (a[end-1] > a[st-2]) ok1 = true;
			}
			else ok1 = true;
			if (end < n)
			{
				if (a[end] > a[st-1]) ok2 = true;
			}
			else
				ok2 = true;
			if (ok1 && ok2) cout<<"yes"<<endl<<st<<" "<<end<<endl;
		}
		else
		{
			cout<<"yes"<<endl;
			cout<<1<<" "<<1<<endl;
		}
	}
	else cout<<"no"<<endl;
}

int main()
{
	int t;
	cin>>t;
	while (t--)
	{
		long long n,k,d1,d2;
		cin>>n>>k>>d1>>d2;
		long long t1,t2,t3;
		t1 = d1;
		t2 = d1 - d2;
		t3 = 0;
		bool yes = false;
		if (t2 >= 0 && t1+t2 <=k && (k - (t1+t2))%3 == 0)
		{
			long long rem = k+ (t1-t2) + (t1-t3);
			if (rem <= n)
			{
				if ((n-rem)%3==0) yes = true;
			}
		}
		t1 = d1+d2;
		t2 = d2;
		t3 = 0;
		if (t1+t2 <=k && (k - (t1+t2))%3 == 0)
		{
			long long rem = k+ (t1-t2) + (t1-t3);
			if (rem <= n)
			{
				if ((n-rem)%3==0) yes = true;
			}
		}

		t1 = d2;
		t2 = d2-d1;
		t3 = 0;
		if (t2 >=0 && t1+t2 <=k && (k - (t1+t2))%3 == 0)
		{
			long long rem = k+ (t1-t2) + (t1-t3);
			if (rem <= n)
			{
				if ((n-rem)%3==0) yes = true;
			}
		}
		t1 = d2;
		t2 = d1;
		t3 = 0;
		if (t1 >= t2 && t1+t2 <=k && (k - (t1+t2))%3 == 0)
		{
			long long rem = k+ (t1-t2) + (t1-t3);
			if (rem <= n)
			{
				if ((n-rem)%3==0) yes = true;
			}
		}
		t1 = d1;
		t2 = d2;
		t3 = 0;
		if (t1 >= t2 && t1+t2 <=k && (k - (t1+t2))%3 == 0)
		{
			long long rem = k+ (t1-t2) + (t1-t3);
			if (rem <= n)
			{
				if ((n-rem)%3==0) yes = true;
			}
		}
		t1 = d1+d2;
		t2 = d1;
		t3 = 0;
		if (t1+t2 <=k && (k - (t1+t2))%3 == 0)
		{
			long long rem = k+ (t1-t2) + (t1-t3);
			if (rem <= n)
			{
				if ((n-rem)%3==0) yes = true;
			}
		}
		if (yes) cout<<"yes"<<endl;
		else cout<<"no"<<endl;
	}
}

int main()
{
	string s;
	cin>>s;
	long long ae = 0;
	long long ao = 0;
	long long be = 0;
	long long bo = 0;
	for (int i = 0; i < s.size(); i++)
	{
		if (s[i] == 'a' && i %2==0) ae++;
		if (s[i] == 'a' && i %2==1) ao++;
		if (s[i] == 'b' && i %2==0) be++;
		if (s[i] == 'b' && i %2==1) bo++;
	}
	long long even = ae*ao + be*bo;
	long long odd = (ae*(ae+1)) / 2 + (be*(be+1))/2 + (ao*(ao+1))/2 + (bo*(bo+1))/2;
	cout<<even<<" "<<odd<<endl;

}

int main()
{
	int n;
	cin>>n;
	string s;
	cin>>s;
	string a[] = {"vaporeon", "jolteon", "flareon", "espeon", "umbreon", "leafeon", "glaceon", "sylveon"};
	for (int i = 0; i < 8; i++)
	{
		if (s.size() == a[i].size())
		{
		bool ok = true;
			for (int j = 0; j < s.size(); j++)
			{
				if (s[j] == '.') continue;
				if (s[j] != a[i][j]) ok = false;
			}
			if (ok) cout<<a[i]<<endl;
		}
	}
}

int main()
{
	int n,m;
	cin>>n>>m;
	if (n > 0 && m > 0)
	{
		double mx = 0.0;
		pair<int,int> best[4];
		pair<int,int> a[4];
		for (int i = 1; i <= m; i++)
		{
			for (int j = 0; j <= m-1; j++)
			{
				a[0] = make_pair(0,0);
				a[1] = make_pair(0,i);
				a[2] = make_pair(n,j);
				a[3] = make_pair(n,m);
				sort(a , a+4);
				double r = 0.0;
					for (int k = 1;k < 4; k++)
					{
						r += sqrt((a[k].first-a[k-1].first)*(a[k].first-a[k-1].first) + (a[k].second-a[k-1].second)*(a[k].second-a[k-1].second));
					}
					if (r >= mx)
					{
						mx = r;
						best[0] = a[0];
						best[1] = a[1];
						best[2] = a[2];
						best[3] = a[3];
					}
				while (next_permutation(a, a+4))
				{
					r = 0.0;
					for (int k = 1;k < 4; k++)
					{
						r += sqrt((a[k].first-a[k-1].first)*(a[k].first-a[k-1].first) + (a[k].second-a[k-1].second)*(a[k].second-a[k-1].second));
					}
					if (r >= mx)
					{
						mx = r;
						best[0] = a[0];
						best[1] = a[1];
						best[2] = a[2];
						best[3] = a[3];
					}
				}
			}
		}
		for (int i = 1; i <= n; i++)
		{
			for (int j = 0; j <= n-1; j++)
			{
				a[0] = make_pair(0,0);
				a[1] = make_pair(i,0);
				a[2] = make_pair(j,m);
				a[3] = make_pair(n,m);
				sort(a , a+4);
				double r = 0.0;
					for (int k = 1;k < 4; k++)
					{
						r += sqrt((a[k].first-a[k-1].first)*(a[k].first-a[k-1].first) + (a[k].second-a[k-1].second)*(a[k].second-a[k-1].second));
					}
					if (r >= mx)
					{
						mx = r;
						best[0] = a[0];
						best[1] = a[1];
						best[2] = a[2];
						best[3] = a[3];
					}
				while (next_permutation(a, a+4))
				{
					r = 0.0;
					for (int k = 1;k < 4; k++)
					{
						r += sqrt((a[k].first-a[k-1].first)*(a[k].first-a[k-1].first) + (a[k].second-a[k-1].second)*(a[k].second-a[k-1].second));
					}
					if (r >= mx)
					{
						mx = r;
						best[0] = a[0];
						best[1] = a[1];
						best[2] = a[2];
						best[3] = a[3];
					}
				}
			}

		}
		for (int i = 0; i < 4; i++) cout<<best[i].first<<" "<<best[i].second<<endl;

	}
	else if (n == 0)
	{
		cout<<0<<" "<<1<<endl;
		cout<<0<<" "<<m<<endl;
		cout<<0<<" "<<0<<endl;
		cout<<0<<" "<<m-1<<endl;
	}
	else
	{
		cout<<1<<" "<<0<<endl;
		cout<<n<<" "<<0<<endl;
		cout<<0<<" "<<0<<endl;
		cout<<n-1<<" "<<0<<endl;
	}
}

int main()
{
	int n1,n2,n3,t1,t2,t3;
	int k;
	cin>>k>>n1>>n2>>n3>>t1>>t2>>t3;
	int a[10001] = {0};
	int b[10001] = {0};
	int c[10001] = {0};
	for (int i = 0; i < k; i++)
	{
		if (i+n1 < k)
		{
			a[i+n1] = a[i] + t1;
		}
	}
	for (int i = 0; i < k; i++)
	{
		b[i] = max(b[i], a[i] + t1);
		if (i+n2 < k)
		{
			b[i+n2] = b[i] + t2;
		}
	}
	for (int i = 0; i < k; i++)
	{
		c[i] = max(c[i], b[i] + t2);
		if (i+n3 < k)
		{
			c[i+n3] = c[i] + t3;
		}
	}
	cout<<c[k-1]+t3<<endl;
}
*/

int main()
{
	int n,m;
	cin>>n>>m;
	set<int> r,c;
	while (m--)
	{
		int a,b;
		cin>>a>>b;
		r.insert(a);
		c.insert(b);
	}
	double dp[3001][3001] = {0.0};
	for (int i = 0; i < n-r.size() + 1; i++)
	{
		for (int j = 0; j <= n-c.size(); j++)
		{
			if (i == j && i == 0) continue;
			if (i > 0 && j > 0)
			{
				dp[i][j] = (((double)i*j) / ((double)n*m))(2+dp[i-1][j-1]);
				dp[i][j] += (((double)i*(n-j)) / ((double)n*m))(2+dp[i-1][j]);
				dp[i][j] += (((double)j*(n-i)) / ((double)n*m))(2+dp[i][j-1]);
				double rem = n*m - i*j - i*(n-j) - j*(n-i);
				dp[i][j] += 2*n*m / rem;
			}
		}
	}
	cout<<dp[n-r.size()][n-c.size()]<<endl;
}


#include <iostream>
#include <string>
#include <iomanip>
#include <fstream>
#include <vector>
#include <algorithm>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
using namespace std;

/*
int main()
{
	int n,m;
	cin>>n>>m;
	int x = min(n,m);
	if (x%2==1)
	{
		cout<<"Akshat"<<endl;
	}
	else cout<<"Malvika"<<endl;
}

int main()
{
	int n;
	cin>>n;
	vector<int> a(n);
	for (int i = 0; i < n; i++)
	{
		cin>>a[i];
	}
	int dec = 0;
	int inc = 0;
	bool in = false;
	bool de = false;
	int st = -1;
	int end = -1;
	int mx = -1;
	vector<int> in1;
	vector<int> in2;
	vector<int> dec;
	for (int i = 1; i < n; i++)
	{
		if (a[i] > a[i-1] && in)
		{
			continue;
		}
		else if (a[i] > a[i-1] && !in)
		{
			inc++;
			in = true;
			end = i;
			de = false;
		}
		else if (a[i] < a[i-1] && !de)
		{
			st = i;
			mx = a[i-1];
			dec++;
			in = false;
			de = true;
		}
	}
	if (de) end = n;

	if (inc <= 2 && dec <= 1)
	{
		if (dec == 1)
		{
			bool ok1,ok2;
			ok1 = false;
			ok2 = false;
			if (st > 1)
			{
				if (a[end-1] > a[st-2]) ok1 = true;
			}
			else ok1 = true;
			if (end < n)
			{
				if (a[end] > a[st-1]) ok2 = true;
			}
			else
				ok2 = true;
			if (ok1 && ok2) cout<<"yes"<<endl<<st<<" "<<end<<endl;
		}
		else
		{
			cout<<"yes"<<endl;
			cout<<1<<" "<<1<<endl;
		}
	}
	else cout<<"no"<<endl;
}

int main()
{
	int t;
	cin>>t;
	while (t--)
	{
		long long n,k,d1,d2;
		cin>>n>>k>>d1>>d2;
		long long t1,t2,t3;
		t1 = d1;
		t2 = d1 - d2;
		t3 = 0;
		bool yes = false;
		if (t2 >= 0 && t1+t2 <=k && (k - (t1+t2))%3 == 0)
		{
			long long rem = k+ (t1-t2) + (t1-t3);
			if (rem <= n)
			{
				if ((n-rem)%3==0) yes = true;
			}
		}
		t1 = d1+d2;
		t2 = d2;
		t3 = 0;
		if (t1+t2 <=k && (k - (t1+t2))%3 == 0)
		{
			long long rem = k+ (t1-t2) + (t1-t3);
			if (rem <= n)
			{
				if ((n-rem)%3==0) yes = true;
			}
		}

		t1 = d2;
		t2 = d2-d1;
		t3 = 0;
		if (t2 >=0 && t1+t2 <=k && (k - (t1+t2))%3 == 0)
		{
			long long rem = k+ (t1-t2) + (t1-t3);
			if (rem <= n)
			{
				if ((n-rem)%3==0) yes = true;
			}
		}
		t1 = d2;
		t2 = d1;
		t3 = 0;
		if (t1 >= t2 && t1+t2 <=k && (k - (t1+t2))%3 == 0)
		{
			long long rem = k+ (t1-t2) + (t1-t3);
			if (rem <= n)
			{
				if ((n-rem)%3==0) yes = true;
			}
		}
		t1 = d1;
		t2 = d2;
		t3 = 0;
		if (t1 >= t2 && t1+t2 <=k && (k - (t1+t2))%3 == 0)
		{
			long long rem = k+ (t1-t2) + (t1-t3);
			if (rem <= n)
			{
				if ((n-rem)%3==0) yes = true;
			}
		}
		t1 = d1+d2;
		t2 = d1;
		t3 = 0;
		if (t1+t2 <=k && (k - (t1+t2))%3 == 0)
		{
			long long rem = k+ (t1-t2) + (t1-t3);
			if (rem <= n)
			{
				if ((n-rem)%3==0) yes = true;
			}
		}
		if (yes) cout<<"yes"<<endl;
		else cout<<"no"<<endl;
	}
}

int main()
{
	string s;
	cin>>s;
	long long ae = 0;
	long long ao = 0;
	long long be = 0;
	long long bo = 0;
	for (int i = 0; i < s.size(); i++)
	{
		if (s[i] == 'a' && i %2==0) ae++;
		if (s[i] == 'a' && i %2==1) ao++;
		if (s[i] == 'b' && i %2==0) be++;
		if (s[i] == 'b' && i %2==1) bo++;
	}
	long long even = ae*ao + be*bo;
	long long odd = (ae*(ae+1)) / 2 + (be*(be+1))/2 + (ao*(ao+1))/2 + (bo*(bo+1))/2;
	cout<<even<<" "<<odd<<endl;

}

int main()
{
	int n;
	cin>>n;
	string s;
	cin>>s;
	string a[] = {"vaporeon", "jolteon", "flareon", "espeon", "umbreon", "leafeon", "glaceon", "sylveon"};
	for (int i = 0; i < 8; i++)
	{
		if (s.size() == a[i].size())
		{
		bool ok = true;
			for (int j = 0; j < s.size(); j++)
			{
				if (s[j] == '.') continue;
				if (s[j] != a[i][j]) ok = false;
			}
			if (ok) cout<<a[i]<<endl;
		}
	}
}

int main()
{
	int n,m;
	cin>>n>>m;
	if (n > 0 && m > 0)
	{
		double mx = 0.0;
		pair<int,int> best[4];
		pair<int,int> a[4];
		for (int i = 1; i <= m; i++)
		{
			for (int j = 0; j <= m-1; j++)
			{
				a[0] = make_pair(0,0);
				a[1] = make_pair(0,i);
				a[2] = make_pair(n,j);
				a[3] = make_pair(n,m);
				sort(a , a+4);
				double r = 0.0;
					for (int k = 1;k < 4; k++)
					{
						r += sqrt((a[k].first-a[k-1].first)*(a[k].first-a[k-1].first) + (a[k].second-a[k-1].second)*(a[k].second-a[k-1].second));
					}
					if (r >= mx)
					{
						mx = r;
						best[0] = a[0];
						best[1] = a[1];
						best[2] = a[2];
						best[3] = a[3];
					}
				while (next_permutation(a, a+4))
				{
					r = 0.0;
					for (int k = 1;k < 4; k++)
					{
						r += sqrt((a[k].first-a[k-1].first)*(a[k].first-a[k-1].first) + (a[k].second-a[k-1].second)*(a[k].second-a[k-1].second));
					}
					if (r >= mx)
					{
						mx = r;
						best[0] = a[0];
						best[1] = a[1];
						best[2] = a[2];
						best[3] = a[3];
					}
				}
			}
		}
		for (int i = 1; i <= n; i++)
		{
			for (int j = 0; j <= n-1; j++)
			{
				a[0] = make_pair(0,0);
				a[1] = make_pair(i,0);
				a[2] = make_pair(j,m);
				a[3] = make_pair(n,m);
				sort(a , a+4);
				double r = 0.0;
					for (int k = 1;k < 4; k++)
					{
						r += sqrt((a[k].first-a[k-1].first)*(a[k].first-a[k-1].first) + (a[k].second-a[k-1].second)*(a[k].second-a[k-1].second));
					}
					if (r >= mx)
					{
						mx = r;
						best[0] = a[0];
						best[1] = a[1];
						best[2] = a[2];
						best[3] = a[3];
					}
				while (next_permutation(a, a+4))
				{
					r = 0.0;
					for (int k = 1;k < 4; k++)
					{
						r += sqrt((a[k].first-a[k-1].first)*(a[k].first-a[k-1].first) + (a[k].second-a[k-1].second)*(a[k].second-a[k-1].second));
					}
					if (r >= mx)
					{
						mx = r;
						best[0] = a[0];
						best[1] = a[1];
						best[2] = a[2];
						best[3] = a[3];
					}
				}
			}

		}
		for (int i = 0; i < 4; i++) cout<<best[i].first<<" "<<best[i].second<<endl;

	}
	else if (n == 0)
	{
		cout<<0<<" "<<1<<endl;
		cout<<0<<" "<<m<<endl;
		cout<<0<<" "<<0<<endl;
		cout<<0<<" "<<m-1<<endl;
	}
	else
	{
		cout<<1<<" "<<0<<endl;
		cout<<n<<" "<<0<<endl;
		cout<<0<<" "<<0<<endl;
		cout<<n-1<<" "<<0<<endl;
	}
}

int main()
{
	int n1,n2,n3,t1,t2,t3;
	int k;
	cin>>k>>n1>>n2>>n3>>t1>>t2>>t3;
	int a[10001] = {0};
	int b[10001] = {0};
	int c[10001] = {0};
	for (int i = 0; i < k; i++)
	{
		if (i+n1 < k)
		{
			a[i+n1] = a[i] + t1;
		}
	}
	for (int i = 0; i < k; i++)
	{
		b[i] = max(b[i], a[i] + t1);
		if (i+n2 < k)
		{
			b[i+n2] = b[i] + t2;
		}
	}
	for (int i = 0; i < k; i++)
	{
		c[i] = max(c[i], b[i] + t2);
		if (i+n3 < k)
		{
			c[i+n3] = c[i] + t3;
		}
	}
	cout<<c[k-1]+t3<<endl;
}

*/

int main()
{
	int n,m;
	cin>>n>>m;
	set<int> r,c;
	while (m--)
	{
		int a,b;
		cin>>a>>b;
		r.insert(a);
		c.insert(b);
	}
	vector<vector<double> > dp(n+1, vector<double> (n+1, 0));

	for (int i = 0; i <= n-r.size(); i++)
	{
		for (int j = 0; j <= n-c.size(); j++)
		{
			dp[i][j] = 0.0;
			if (i == j && i == 0) continue;
			dp[i][j] = 1;
			if (i > 0 && j > 0)
			{
				dp[i][j] += (((double)i*j) / ((double)n*n)) * (dp[i-1][j-1]);
			}
			if (i > 0) dp[i][j] += (((double)i*(n-j)) / ((double)n*n)) * (dp[i-1][j]);
			if (j > 0) dp[i][j] += (((double)j*(n-i)) / ((double)n*n)) * (dp[i][j-1]);
			double rem = (n-j)*(n-i);
			dp[i][j] /= (1.0- rem / ((double)n*n));
		}
	}
	cout<<dp[n-r.size()][n-c.size()]<<endl;

}


#include <iostream>
#include <string>
#include <iomanip>
#include <fstream>
#include <vector>
#include <algorithm>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
using namespace std;

/*
int main()
{
	int n,m;
	cin>>n>>m;
	int x = min(n,m);
	if (x%2==1)
	{
		cout<<"Akshat"<<endl;
	}
	else cout<<"Malvika"<<endl;
}

int main()
{
	int n;
	cin>>n;
	vector<int> a(n);
	for (int i = 0; i < n; i++)
	{
		cin>>a[i];
	}
	int dec = 0;
	int inc = 0;
	bool in = false;
	bool de = false;
	int st = -1;
	int end = -1;
	int mx = -1;
	vector<int> in1;
	vector<int> in2;
	vector<int> dec;
	for (int i = 1; i < n; i++)
	{
		if (a[i] > a[i-1] && in)
		{
			continue;
		}
		else if (a[i] > a[i-1] && !in)
		{
			inc++;
			in = true;
			end = i;
			de = false;
		}
		else if (a[i] < a[i-1] && !de)
		{
			st = i;
			mx = a[i-1];
			dec++;
			in = false;
			de = true;
		}
	}
	if (de) end = n;

	if (inc <= 2 && dec <= 1)
	{
		if (dec == 1)
		{
			bool ok1,ok2;
			ok1 = false;
			ok2 = false;
			if (st > 1)
			{
				if (a[end-1] > a[st-2]) ok1 = true;
			}
			else ok1 = true;
			if (end < n)
			{
				if (a[end] > a[st-1]) ok2 = true;
			}
			else
				ok2 = true;
			if (ok1 && ok2) cout<<"yes"<<endl<<st<<" "<<end<<endl;
		}
		else
		{
			cout<<"yes"<<endl;
			cout<<1<<" "<<1<<endl;
		}
	}
	else cout<<"no"<<endl;
}

int main()
{
	int t;
	cin>>t;
	while (t--)
	{
		long long n,k,d1,d2;
		cin>>n>>k>>d1>>d2;
		long long t1,t2,t3;
		t1 = d1;
		t2 = d1 - d2;
		t3 = 0;
		bool yes = false;
		if (t2 >= 0 && t1+t2 <=k && (k - (t1+t2))%3 == 0)
		{
			long long rem = k+ (t1-t2) + (t1-t3);
			if (rem <= n)
			{
				if ((n-rem)%3==0) yes = true;
			}
		}
		t1 = d1+d2;
		t2 = d2;
		t3 = 0;
		if (t1+t2 <=k && (k - (t1+t2))%3 == 0)
		{
			long long rem = k+ (t1-t2) + (t1-t3);
			if (rem <= n)
			{
				if ((n-rem)%3==0) yes = true;
			}
		}

		t1 = d2;
		t2 = d2-d1;
		t3 = 0;
		if (t2 >=0 && t1+t2 <=k && (k - (t1+t2))%3 == 0)
		{
			long long rem = k+ (t1-t2) + (t1-t3);
			if (rem <= n)
			{
				if ((n-rem)%3==0) yes = true;
			}
		}
		t1 = d2;
		t2 = d1;
		t3 = 0;
		if (t1 >= t2 && t1+t2 <=k && (k - (t1+t2))%3 == 0)
		{
			long long rem = k+ (t1-t2) + (t1-t3);
			if (rem <= n)
			{
				if ((n-rem)%3==0) yes = true;
			}
		}
		t1 = d1;
		t2 = d2;
		t3 = 0;
		if (t1 >= t2 && t1+t2 <=k && (k - (t1+t2))%3 == 0)
		{
			long long rem = k+ (t1-t2) + (t1-t3);
			if (rem <= n)
			{
				if ((n-rem)%3==0) yes = true;
			}
		}
		t1 = d1+d2;
		t2 = d1;
		t3 = 0;
		if (t1+t2 <=k && (k - (t1+t2))%3 == 0)
		{
			long long rem = k+ (t1-t2) + (t1-t3);
			if (rem <= n)
			{
				if ((n-rem)%3==0) yes = true;
			}
		}
		if (yes) cout<<"yes"<<endl;
		else cout<<"no"<<endl;
	}
}

int main()
{
	string s;
	cin>>s;
	long long ae = 0;
	long long ao = 0;
	long long be = 0;
	long long bo = 0;
	for (int i = 0; i < s.size(); i++)
	{
		if (s[i] == 'a' && i %2==0) ae++;
		if (s[i] == 'a' && i %2==1) ao++;
		if (s[i] == 'b' && i %2==0) be++;
		if (s[i] == 'b' && i %2==1) bo++;
	}
	long long even = ae*ao + be*bo;
	long long odd = (ae*(ae+1)) / 2 + (be*(be+1))/2 + (ao*(ao+1))/2 + (bo*(bo+1))/2;
	cout<<even<<" "<<odd<<endl;

}

int main()
{
	int n;
	cin>>n;
	string s;
	cin>>s;
	string a[] = {"vaporeon", "jolteon", "flareon", "espeon", "umbreon", "leafeon", "glaceon", "sylveon"};
	for (int i = 0; i < 8; i++)
	{
		if (s.size() == a[i].size())
		{
		bool ok = true;
			for (int j = 0; j < s.size(); j++)
			{
				if (s[j] == '.') continue;
				if (s[j] != a[i][j]) ok = false;
			}
			if (ok) cout<<a[i]<<endl;
		}
	}
}

int main()
{
	int n,m;
	cin>>n>>m;
	if (n > 0 && m > 0)
	{
		double mx = 0.0;
		pair<int,int> best[4];
		pair<int,int> a[4];
		for (int i = 1; i <= m; i++)
		{
			for (int j = 0; j <= m-1; j++)
			{
				a[0] = make_pair(0,0);
				a[1] = make_pair(0,i);
				a[2] = make_pair(n,j);
				a[3] = make_pair(n,m);
				sort(a , a+4);
				double r = 0.0;
					for (int k = 1;k < 4; k++)
					{
						r += sqrt((a[k].first-a[k-1].first)*(a[k].first-a[k-1].first) + (a[k].second-a[k-1].second)*(a[k].second-a[k-1].second));
					}
					if (r >= mx)
					{
						mx = r;
						best[0] = a[0];
						best[1] = a[1];
						best[2] = a[2];
						best[3] = a[3];
					}
				while (next_permutation(a, a+4))
				{
					r = 0.0;
					for (int k = 1;k < 4; k++)
					{
						r += sqrt((a[k].first-a[k-1].first)*(a[k].first-a[k-1].first) + (a[k].second-a[k-1].second)*(a[k].second-a[k-1].second));
					}
					if (r >= mx)
					{
						mx = r;
						best[0] = a[0];
						best[1] = a[1];
						best[2] = a[2];
						best[3] = a[3];
					}
				}
			}
		}
		for (int i = 1; i <= n; i++)
		{
			for (int j = 0; j <= n-1; j++)
			{
				a[0] = make_pair(0,0);
				a[1] = make_pair(i,0);
				a[2] = make_pair(j,m);
				a[3] = make_pair(n,m);
				sort(a , a+4);
				double r = 0.0;
					for (int k = 1;k < 4; k++)
					{
						r += sqrt((a[k].first-a[k-1].first)*(a[k].first-a[k-1].first) + (a[k].second-a[k-1].second)*(a[k].second-a[k-1].second));
					}
					if (r >= mx)
					{
						mx = r;
						best[0] = a[0];
						best[1] = a[1];
						best[2] = a[2];
						best[3] = a[3];
					}
				while (next_permutation(a, a+4))
				{
					r = 0.0;
					for (int k = 1;k < 4; k++)
					{
						r += sqrt((a[k].first-a[k-1].first)*(a[k].first-a[k-1].first) + (a[k].second-a[k-1].second)*(a[k].second-a[k-1].second));
					}
					if (r >= mx)
					{
						mx = r;
						best[0] = a[0];
						best[1] = a[1];
						best[2] = a[2];
						best[3] = a[3];
					}
				}
			}

		}
		for (int i = 0; i < 4; i++) cout<<best[i].first<<" "<<best[i].second<<endl;

	}
	else if (n == 0)
	{
		cout<<0<<" "<<1<<endl;
		cout<<0<<" "<<m<<endl;
		cout<<0<<" "<<0<<endl;
		cout<<0<<" "<<m-1<<endl;
	}
	else
	{
		cout<<1<<" "<<0<<endl;
		cout<<n<<" "<<0<<endl;
		cout<<0<<" "<<0<<endl;
		cout<<n-1<<" "<<0<<endl;
	}
}

int main()
{
	int n1,n2,n3,t1,t2,t3;
	int k;
	cin>>k>>n1>>n2>>n3>>t1>>t2>>t3;
	int a[10001] = {0};
	int b[10001] = {0};
	int c[10001] = {0};
	for (int i = 0; i < k; i++)
	{
		if (i+n1 < k)
		{
			a[i+n1] = a[i] + t1;
		}
	}
	for (int i = 0; i < k; i++)
	{
		b[i] = max(b[i], a[i] + t1);
		if (i+n2 < k)
		{
			b[i+n2] = b[i] + t2;
		}
	}
	for (int i = 0; i < k; i++)
	{
		c[i] = max(c[i], b[i] + t2);
		if (i+n3 < k)
		{
			c[i+n3] = c[i] + t3;
		}
	}
	cout<<c[k-1]+t3<<endl;
}
*/

int main()
{
	int n,m;
	cin>>n>>m;
	set<int> r,c;
	while (m--)
	{
		int a,b;
		cin>>a>>b;
		r.insert(a);
		c.insert(b);
	}
	double dp[3001][3001] = {0.0};
	for (int i = 0; i < n-r.size() + 1; i++)
	{
		for (int j = 0; j <= n-c.size(); j++)
		{
			if (i == j && i == 0) continue;
			if (i > 0 && j > 0)
			{
				dp[i][j] = (((double)i*j) / ((double)n*m)) * (2+dp[i-1][j-1]);
			}
			dp[i][j] += (((double)i*(n-j)) / ((double)n*m)) * (2+dp[i-1][j]);
			dp[i][j] += (((double)j*(n-i)) / ((double)n*m)) * (2+dp[i][j-1]);
			double rem = n*m - i*j - i*(n-j) - j*(n-i);
			dp[i][j] += 2*n*m / rem;
		}
	}
	cout<<dp[n-r.size()][n-c.size()]<<endl;
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.InputMismatchException;
import java.io.IOException;
import java.io.InputStream;

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

    static class BPaintingTheWall {
        public void solve(int testNumber, InputReader in, PrintWriter out) {
            int n = in.readInt();
            int m = in.readInt();

            int[][] wall = new int[n][n];
            for (int i = 0; i < m; i++) {
                int r = in.readInt() - 1;
                int c = in.readInt() - 1;

                wall[r][c] = 1;
            }
            int blankrow = 0, blankcol = 0;
            for (int i = 0; i < n; i++) {
                int cnt1 = 0, cnt2 = 0;
                for (int j = 0; j < n; j++) {
                    if (wall[i][j] == 1) cnt1++;
                    if (wall[j][i] == 1) cnt2++;
                }
                if (cnt1 == 0) blankrow++;
                if (cnt2 == 0) blankcol++;
            }
            double[][] dp = new double[n + 1][n + 1];
            dp[0][0] = 0;

            for (int i = 0; i <= n; i++) {
                for (int j = 0; j <= n; j++) {
                    if (i == 0 && j == 0) continue;
                    double sum = n * n;
                    if (i > 0 && j > 0) sum += dp[i - 1][j - 1] * i * j;
                    if (i > 0) sum += dp[i - 1][j] * i * (n - j);
                    if (j > 0) sum += dp[i][j - 1] * j * (n - i);
                    dp[i][j] = sum / (n * n - (n - i) * (n - j));
                }
            }
            out.println(dp[blankrow][blankcol]);
        }

    }

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

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

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

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

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

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

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

        }

    }
}


import java.io.OutputStreamWriter;
import java.io.BufferedWriter;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Random;
import java.io.Writer;
import java.util.List;
import java.io.IOException;
import java.util.Arrays;
import java.util.InputMismatchException;
import java.util.ArrayList;
import java.util.NoSuchElementException;
import java.math.BigInteger;
import java.io.InputStream;

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

class TaskB {
    public void solve(int testNumber, InputReader in, OutputWriter out) {
        int n=in.readInt(), m=in.readInt();
        double[][] dp=new double[n+1][n+1];
        for (int i=1; i<=n; i++) dp[i][0]=dp[0][i]=1.0*n/i+dp[i-1][0];
        for (int i=1; i<=n; i++) for (int j=1; j<=n; j++) dp[i][j]=(1.0*i/n*j/n*(1+dp[i-1][j-1])+1.0*i/n*(n-j)/n*(1+dp[i-1][j])+1.0*(n-i)/n*j/n*(1+dp[i][j-1])+1.0*(n-i)/n*(n-j)/n)/(1-1.0*(n-i)/n*(n-j)/n);
        IntSet setx=new IntHashSet(), sety=new IntHashSet();
        while (m-->0) {
            setx.add(in.readInt());
            sety.add(in.readInt());
        }
        out.printLine(dp[n-setx.size()][n-sety.size()]);
    }
}

class InputReader {

    private InputStream stream;
    private byte[] buf = new byte[1024];
    private int curChar;
    private int numChars;
    private SpaceCharFilter filter;

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

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

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

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

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

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

class OutputWriter {
    private final PrintWriter writer;

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

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

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

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

}

abstract class IntSet extends IntCollection {
}

class IntHashSet extends IntSet {
    private static final Random RND = new Random();
    private static final int[] SHIFTS = new int[4];
    private static final byte PRESENT_MASK = 1;

    static {
        for (int i = 0; i < 4; i++)
            SHIFTS[i] = RND.nextInt(31) + 1;
    }

    private int size;
    private int realSize;
    private int[] values;
    private byte[] present;
    private int step;
    private int ratio;

    public IntHashSet() {
        this(3);
    }

    public IntHashSet(int capacity) {
        capacity = Math.max(capacity, 1);
        values = new int[capacity];
        present = new byte[capacity];
        ratio = 2;
        initStep(capacity);
    }

    private void initStep(int capacity) {
        step = RND.nextInt(capacity - 2) + 1;
        while (IntegerUtils.gcd(step, capacity) != 1)
            step++;
    }

    public int size() {
        return size;
    }

    public void add(int value) {
        ensureCapacity((realSize + 1) * ratio + 2);
        int current = getHash(value);
        while (present[current] != 0) {
            if ((present[current] & PRESENT_MASK) != 0 && values[current] == value) {
                return;
            }
            current += step;
            if (current >= values.length)
                current -= values.length;
        }
        while ((present[current] & PRESENT_MASK) != 0) {
            current += step;
            if (current >= values.length)
                current -= values.length;
        }
        if (present[current] == 0) {
            realSize++;
        }
        present[current] = PRESENT_MASK;
        values[current] = value;
        size++;
    }

    private int getHash(int value) {
        int result = value;
        for (int i : SHIFTS)
            result ^= value >> i;
        result %= values.length;
        if (result < 0)
            result += values.length;
        return result;
    }

    private void ensureCapacity(int capacity) {
        if (values.length < capacity) {
            capacity = Math.max(capacity * 2, values.length);
            rebuild(capacity);
        }
    }

    private void rebuild(int capacity) {
        initStep(capacity);
        int[] oldValues = values;
        byte[] oldPresent = present;
        values = new int[capacity];
        present = new byte[capacity];
        size = 0;
        realSize = 0;
        for (int i = 0; i < oldValues.length; i++) {
            if ((oldPresent[i] & PRESENT_MASK) == PRESENT_MASK)
                add(oldValues[i]);
        }
    }

}

abstract class IntCollection {
    public abstract int size();
    public abstract void add(int value);

}

class IntegerUtils {

    public static int gcd(int a, int b) {
        a = Math.abs(a);
        b = Math.abs(b);
        while (b != 0) {
            int temp = a % b;
            a = b;
            b = temp;
        }
        return a;
    }

}


import java.text.DecimalFormat;
import java.util.*;
import java.io.*;

public class Main {
    private static int n;
    private static Double [] [] dp;

    private static double solve(int r,int c) {
        if (r < 0 || c < 0) return 0;
        if (r == 0 && c == 0) return 0;

        if (dp[r][c] != null) return dp[r][c];

        int affect_both = r*c;
        int affect_row = r*n - affect_both,
                affect_col = c*n - affect_both;
        int rem = n*n - affect_row - affect_col - affect_both;

        double ret = solve(r,c-1) * affect_col
                + solve(r-1,c)*affect_row
                + solve(r-1,c-1)*affect_both + n*n;

        if (rem < n*n)
            ret /= n*n - rem;
        else
            ret /= n*n;
        dp[r][c] = ret;
//        System.err.println(r + " " + c + " -> " + ret);
        return ret;
    }
    public static void main(String[] args) throws Exception {
        IO io = new IO(null, null);
        n = io.getNextInt();
        int m = io.getNextInt();
        HashSet<Integer> R = new HashSet<>();
        HashSet<Integer> C = new HashSet<>();
        for (int i = 0;i < m;i++) {
            R.add(io.getNextInt());
            C.add(io.getNextInt());
        }
        dp = new Double[n+1][n+1];
        io.print(solve(n-R.size(),n-C.size()));
        io.close();
    }

}

class IO{
    private BufferedReader br;
    private StringTokenizer st;
    private PrintWriter writer;
    private String inputFile,outputFile;

    public boolean hasMore() throws IOException{
        if(st != null && st.hasMoreTokens()) return true;
        if(br != null && br.ready()) return true;
        return false;
    }

    public String getNext() throws FileNotFoundException, IOException{
        while(st == null || !st.hasMoreTokens()) st = new StringTokenizer(br.readLine());
        return st.nextToken();
    }

    public String getNextLine() throws FileNotFoundException, IOException{
        return br.readLine().trim();
    }

    public int getNextInt() throws FileNotFoundException, IOException{
        return Integer.parseInt(getNext());
    }
    public long getNextLong() throws FileNotFoundException, IOException{
        return Long.parseLong(getNext());
    }

    public void print(double x,int num_digits) throws  IOException{
        writer.printf("%." + num_digits + "f" ,x);
    }
    public void println(double x,int num_digits) throws  IOException{
        writer.printf("%." + num_digits + "f\n" ,x);
    }
    public void print(Object o) throws  IOException{
        writer.print(o.toString());
    }

    public void println(Object o) throws  IOException{
        writer.println(o.toString());
    }
    public IO(String x,String y) throws FileNotFoundException, IOException{
        inputFile = x;
        outputFile = y;
        if(x != null) br = new BufferedReader(new FileReader(inputFile));
        else br = new BufferedReader(new InputStreamReader(System.in));
        if(y != null) writer = new PrintWriter(new BufferedWriter(new FileWriter(outputFile)));
        else writer = new PrintWriter(new OutputStreamWriter(System.out));
    }

    protected void close() throws IOException{
        br.close();
        writer.close();
    }
    public void outputArr(Object [] A) throws IOException{
        int L = A.length;
        for (int i = 0;i < L;i++) {
            if(i > 0) writer.print(" ");
            writer.print(A[i]);
        }
        writer.print("\n");
    }
}


import java.io.*;
import static java.lang.Math.*;

import java.lang.reflect.Array;
import java.math.BigInteger;
import java.util.*;
import java.lang.*;

public class Main {
    final static boolean debug = false;
    final static String fileName = "";
    final static boolean useFiles = false;

    public static void main(String[] args) throws FileNotFoundException {
        PrintWriter writer = new PrintWriter(System.out);
        new Task(new InputReader(System.in), writer).solve();
        writer.close();
    }
}

class InputReader {
    public BufferedReader reader;
    public StringTokenizer tokenizer;

    public InputReader(InputStream stream) {
        reader = new BufferedReader(new InputStreamReader(stream), 32768);
        tokenizer = null;
    }

    public String next() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                tokenizer = new StringTokenizer(reader.readLine());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return tokenizer.nextToken();
    }

    public double nextDouble() {
        return Double.parseDouble(next());
    }

    public int nextInt() {
        return Integer.parseInt(next());
    }

    public long nextLong() {
        return Long.parseLong(next());
    }

    public byte nextByte() {
        return Byte.parseByte(next());
    }
}

class Task {
    public void solve() {
        int n = in.nextInt();
        int m = in.nextInt();

        boolean[] px = new boolean[n];
        boolean[] py = new boolean[n];
        for (int i = 0; i < m; i++){
            int x = in.nextInt() - 1;
            int y = in.nextInt() - 1;
            px[x] = true;
            py[y] = true;
        }

        int a = 0, b = 0;
        for (int i = 0; i < n; i++){
            if (px[i]) a++;
            if (py[i]) b++;
        }

        double[][] d = new double[n + 2][n + 2];
        d[n][n] = 0;
        for (int x = n; x >= a; x--){
            for (int y = n; y >= b; y--){
                if (x == n && y == n) continue;
                double gx = x / (double) n;
                double gy = y / (double) n;
                d[x][y] = ((1 - gx) * (1 - gy) * (d[x + 1][y + 1] + 1)
                        + (1 - gx) * gy * (d[x + 1][y] + 1)
                        + gx * (1 - gy) * (d[x][y + 1] + 1)
                        + gx * gy) / (1 - gx * gy);
            }
        }
        out.println(d[a][b]);
    }

    private InputReader in;
    private PrintWriter out;

    Task(InputReader in, PrintWriter out) {
        this.in = in;
        this.out = out;
    }
}


#include<bits/stdc++.h>
#define debug(x) cout<<#x<<"="<<x<<endl
using namespace std;
const int maxn = 2009;
int n,m;
double f[maxn][maxn];
bool vis1[maxn],vis2[maxn];
int c1,c2;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
double dp(int x,int y)
{
	if(f[x][y]!=-1) return f[x][y];
	if(x>n||y>n) return 0;
	return f[x][y]=(1.0*(n-x)*y/n/n*dp(x+1,y)+1.0*x*(n-y)/n/n*dp(x,y+1)+1.0*(n-x)*(n-y)/n/n*dp(x+1,y+1)+1)/(1.0*(n*n-x*y)/(n*n));
}
int main()
{
	n=read();m=read();
	while(m--)
	{
		int x=read(),y=read();
		vis1[x]=vis2[y]=1;
	}
	for(int i=1;i<=n;i++)
	{
		if(vis1[i]) c1++;
		if(vis2[i]) c2++;
	}
	for(int i=0;i<=n;i++)
		for(int j=0;j<=n;j++)
			f[i][j]=-1;
	f[n][n]=0;
	printf("%.6lf",dp(c1,c2));
	return 0;
}


#include<stdio.h>
#include<iostream>
#include<map>
using namespace std;

map<int,bool> v,h;
int n,M,x,y;
double t[2300][2300];

int main()
{
    cin>>n>>M;
    for(int i=1;i<=M;++i)
    {
        cin>>x>>y;
        v[x]=1;
        h[y]=1;
    }
    int R = n - v.size();
    int C = n - h.size();
    t[0][0] = 0;

    for(int i=0;i<=R;++i)
    {
        for(int j=0;j<=C;++j)
        {
            if(i && j)
            {
                t[i][j] += t[i-1][j-1]*i*j;
            }
            if(i)
            {
                t[i][j] += t[i-1][j]*(n-j)*i;
            }
            if(j)
            {
                t[i][j] += t[i][j-1]*j*(n-i);
            }

            if(i||j)
            {
                t[i][j] += n*n;
                t[i][j] = t[i][j]/(n*i+n*j-i*j);
            }
        }
    }

    cout<<t[R][C];
    return 0;
}


#include <stdio.h>
#include <algorithm>
#include <vector>
using namespace std;
int used[51];
bool use[51];
int attempt;
vector <int> danger[51];
void dfs(int v){
    for(int i = danger[v].size() - 1; i >= 0 ; i --)
    {
        int to = danger[v][i];
        if(use[to])continue;
        attempt ++;
        use[to] = true;
        dfs(to);
    }
}
int main(){
    int n, m;
    scanf("%d %d",&n,&m);
        for(int i = 0,a,b ; i < m ; i ++)
        {
            scanf("%d %d",&a,&b);
                danger[a].push_back(b);
                danger[b].push_back(a);
        }
        for(int i = 1 ; i <= n ; i ++)
            if(use[i] == 0){
                    attempt = 0;
                    dfs(i);
                        for(int _i = 1 ; _i <= n ; _i ++)
                        if(use[_i] && used[_i] == 0) used[_i] = attempt;

            }
        sort(used+1,used+n+1);
        unsigned __int64 Danger = 1ll;
            for(int i = 1; i <= n ; i++)
                if(used[i] == used[i-1] && used[i] != 0) Danger *= 2ll;
            printf("%I64d",Danger);
}


#include <stdio.h>
#include <algorithm>
#include <vector>
using namespace std;
int used[51];
bool use[51];
int attempt;
vector <int> danger[51];
void dfs(int v){
    for(int i = danger[v].size() - 1; i >= 0 ; i --)
    {
        int to = danger[v][i];
        if(use[to])continue;
        attempt ++;
        use[to] = true;
        dfs(to);
    }
}
int main(){
    int n, m;
    scanf("%d %d",&n,&m);
        for(int i = 0,a,b ; i < m ; i ++)
        {
            scanf("%d %d",&a,&b);
                danger[a].push_back(b);
                danger[b].push_back(a);
        }
        for(int i = 1 ; i <= n ; i ++)
            if(use[i] == 0){
                    attempt = 0;
                    dfs(i);
                        for(int _i = 1 ; _i <= n ; _i ++)
                        if(use[_i] && used[_i] == 0) used[_i] = attempt;

            }
        sort(used+1,used+n+1);
        __int64 Danger = 1ll;
            for(int i = 1; i <= n ; i++)
                if(used[i] == used[i-1] && used[i] != 0) Danger *= 2ll;
            printf("%I64d",Danger);
}


#include <stdio.h>
#include <algorithm>
#include <vector>
using namespace std;
vector <int>g[51];
bool used[51];
int seen[51];
int attempt;
void dfs(int u){
    seen[u] = attempt;
    for(int i = g[u].size() - 1; i >= 0 ; i --){
        int v = g[u][i];
            if(used[v]) continue;
                used[v] = true;
            dfs(v);
    }
}
int main(){
    int n, m;
    scanf("%d %d",&n,&m);
        for(int i = 0,a ,b ; i < m ; i ++)
        {
            scanf("%d %d",&a,&b);
                g[a].push_back(b);
                g[b].push_back(a);
        }
        for(int i = 1; i <= n ; i ++)
            if(!used[i]){
                    attempt ++;
                    dfs(i);
            }
            __int64 Danger = 1;
        sort(seen+1,seen+n+1);
            for(int i = 1 ; i <= n ; i ++)
                if(seen[i] == seen[i-1] && seen[i] != 0) Danger *= 2ll;
        printf("%I64d",Danger);
}


#include<stdio.h>
#include<algorithm>
#include<string>
#include<vector>
#include<map>

long long int n,m,p[100],e[2000],q[100];

long long int find(long long int v) {
    if(p[v]==v)return v;
    return (p[v]=find(p[v]));
}
void un(long long int v1,long long int v2) {
    long long int p1,p2;
    p1=find(v1);
    p2=find(v2);
    if(p1==p2) {
        e[p1]++;
    }else{
        e[p2]+=e[p1]+1;
        p[p1]=p2;
        q[p2]+=q[p1];
    }
}
int st(long long int w1,long long int w2) {
    int z,x=1;
    for(z=0;z<w2;z++) {
        x=x*w1;
    }
    return x;
}
void solve() {
    long long int a,b,i,j,sum=1;
    for(i=0;i<n;i++) {
        p[i]=i;
        q[i]=1;
    }
    for(i=0;i<2000;i++)e[i]=0;
    for(i=0;i<m;i++) {
        scanf("%I64d%I64d",&a,&b);
        un(a-1,b-1);
    }
    for(i=0;i<n;i++) {
        if(p[i]=i) {
            sum=sum*st(2,e[i]);
        }
    }
    if(m>=2)sum/=2;
    printf("%I64d",sum);
    return;
}
int main() {
    #pragma comment(linker,"/STACK:1073741824")
     #ifndef ONLINE_JUDGE
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
     #endif
    while(scanf("%I64d%I64d",&n,&m)!=EOF)solve();
}


#include<stdio.h>
#include<algorithm>
#include<string>
#include<vector>
#include<map>

long long int n,m,p[100],e[2000],q[100];

long long int find(long long int v) {
    if(p[v]==v)return v;
    return (p[v]=find(p[v]));
}
void un(long long int v1,long long int v2) {
    long long int p1,p2;
    p1=find(v1);
    p2=find(v2);
    if(p1==p2) {
        e[p1]++;
    }else{
        e[p2]+=e[p1]+1;
        p[p1]=p2;
        q[p2]+=q[p1];
    }
}
int st(long long int w1,long long int w2) {
    int z,x=1;
    for(z=0;z<w2;z++) {
        x=x*w1;
    }
    return x;
}
void solve() {
    long long int a,b,i,j,sum=1,k=0;
    for(i=0;i<n;i++) {
        p[i]=i;
        q[i]=1;
    }
    for(i=0;i<2000;i++)e[i]=0;
    for(i=0;i<m;i++) {
        scanf("%I64d%I64d",&a,&b);
        un(a-1,b-1);
    }
    for(i=0;i<n;i++) {
        if(p[i]==i) {
            /*k++;
            if(k==1) {
                sum=sum*st(2,q[i]-1);
            }else{
                sum=sum*st(2,q[i]-2);
            }*/

            sum*=1<<(q[i]-1);
        }
    }
    //if(m>=2)sum/=st(2,m+1);
    printf("%I64d",sum);
    return;
}
int main() {
    #pragma comment(linker,"/STACK:1073741824")
     #ifndef ONLINE_JUDGE
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
     #endif
    while(scanf("%I64d%I64d",&n,&m)!=EOF)solve();
}


#include<stdio.h>
#include<algorithm>
#include<string>
#include<vector>
#include<map>

long long int n,m,p[100],e[2000],q[100];

long long int find(long long int v) {
    if(p[v]==v)return v;
    return (p[v]=find(p[v]));
}
void un(long long int v1,long long int v2) {
    long long int p1,p2;
    p1=find(v1);
    p2=find(v2);
    if(p1==p2) {
        e[p1]++;
    }else{
        e[p2]+=e[p1]+1;
        p[p1]=p2;
        q[p2]+=q[p1];
    }
}
int st(long long int w1,long long int w2) {
    int z,x=1;
    for(z=0;z<w2;z++) {
        x=x*w1;
    }
    return x;
}
void solve() {
    long long int a,b,i,j,sum=1,k=0;
    for(i=0;i<n;i++) {
        p[i]=i;
        q[i]=1;
    }
    for(i=0;i<2000;i++)e[i]=0;
    for(i=0;i<m;i++) {
        scanf("%I64d%I64d",&a,&b);
        un(a-1,b-1);
    }
    for(i=0;i<n;i++) {
        if(p[i]==i) {
            /*k++;
            if(k==1) {
                sum=sum*st(2,q[i]-1);
            }else{
                sum=sum*st(2,q[i]-2);
            }*/

            sum*=((long long int)1)<<(q[i]-1);
        }
    }
    //if(m>=2)sum/=st(2,m+1);
    printf("%I64d",sum);
    return;
}
int main() {
    #pragma comment(linker,"/STACK:1073741824")
     #ifndef ONLINE_JUDGE
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
     #endif
    while(scanf("%I64d%I64d",&n,&m)!=EOF)solve();
}


#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <cmath>
#include <queue>
#include <memory>
#include <functional>
#include <set>

typedef unsigned int uint;
typedef long long ll;

using namespace std;

const int INF = 1e+9;

int const MAX = 100;

ll n, m, answer = 1;
bool used[MAX];
vector< ll> g[MAX];

void Dfs( ll x )
{
	used[x] = true;
	answer *= 2;

	for (vector< ll>::iterator it = g[x].begin(); it != g[x].end(); ++it)
	{
		if (!used[*it])
		{
			Dfs( *it );
		}
	}
}

ll main( )
{
	FILE* ci;
	FILE* co;

#ifdef _DEBUG
	freopen_s( &ci, "input.txt", "r", stdin );
	freopen_s( &co, "output.txt", "w", stdout );
//#else
//	freopen_s( &ci, "island2.in", "r", stdin );
//	freopen_s( &co, "island2.out", "w", stdout );
#endif

	cin >> n >> m;

	ll a, b;
	for (ll i = 0; i < m; ++i)
	{
		cin >> a >> b;
		--a; --b;
		g[a].push_back( b );
		g[b].push_back( a );
	}

	for (ll i = 0; i < n; ++i)
	{
		if (!used[i])
		{
			Dfs( i );
			answer /= 2;
		}
	}

	cout << answer << endl;
}


#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <cmath>
#include <queue>
#include <memory>
#include <functional>
#include <set>

typedef unsigned int uint;
typedef long long ll;

using namespace std;

const int INF = 1e+9;

int const MAX = 100;

ll n, m, answer = 1;
bool used[MAX];
vector< ll> g[MAX];

void Dfs( ll x )
{
	used[x] = true;
	answer *= 2;

	for (vector< ll>::iterator it = g[x].begin(); it != g[x].end(); ++it)
	{
		if (!used[*it])
		{
			Dfs( *it );
		}
	}
}

int main( )
{
	FILE* ci;
	FILE* co;

#ifdef _DEBUG
	freopen_s( &ci, "input.txt", "r", stdin );
	freopen_s( &co, "output.txt", "w", stdout );
//#else
//	freopen_s( &ci, "island2.in", "r", stdin );
//	freopen_s( &co, "island2.out", "w", stdout );
#endif

	cin >> n >> m;

	ll a, b;
	for (ll i = 0; i < m; ++i)
	{
		cin >> a >> b;
		--a; --b;
		g[a].push_back( b );
		g[b].push_back( a );
	}

	for (ll i = 0; i < n; ++i)
	{
		if (!used[i])
		{
			Dfs( i );
			answer /= 2;
		}
	}

	cout << answer << endl;
}


#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

typedef unsigned int uint;
typedef long long ll;

using namespace std;

int main()
{

#ifdef _DEBUG
	FILE* ci;
	FILE* co;

	freopen_s( &ci, "input.txt", "r", stdin );
	freopen_s( &co, "output.txt", "w", stdout );
#endif

	int n, m;

	cin >> n >> m;

	cout << int(pow( 2, m ));

	return 0;
}


#include <iostream>
#include <vector>
#include <string>
#include <cmath>

typedef unsigned int uint;
typedef long long ll;

using namespace std;

int n = 0, m = 0, step = 0;
vector< vector< bool>> vec;

int WMaxActiv(int x)
{
	int maxx = 0; int indx = -1;

	for (int i = 0; i < n; i++)
	{
		if (vec[x][i] == false) continue;
		if (indx == -1) indx = i;

		int newMax = 0;

		for (int j = 0; j < n; j++)
		{
			if (vec[i][j] == true)
			{
				newMax++;
			}
		}

		if (newMax > maxx)
		{
			maxx = newMax;
			indx = i;
		}
	}

	return indx;
}

void OPACHKI(int x)
{
	while (true)
	{
		int c = WMaxActiv( x );

		if (c == -1) return;
		else
		{
			vec[x][c] = false;
			vec[c][x] = false;
			step++;
			OPACHKI( c );
		}
	}
}

int main()
{
	/*FILE* ci;
	FILE* co;

	freopen_s( &ci, "input.txt", "r", stdin );
	freopen_s( &co, "output.txt", "w", stdout );*/

	cin >> n >> m;

	if (n == 1)
	{
		cout << "1";

		return 0;
	}

	vec.resize( n );

	for (int i = 0; i < n; i++)
	{
		vec[i].resize( n );
	}

	int a, b;
	for (int i = 0; i < m; i++)
	{
		cin >> a >> b;

		vec[a-1][b-1] = true;
		vec[b-1][a-1] = true;
	}

	int maxx = 0; int indx = -1;

	for (int i = 0; i < n; i++)
	{
		int newMax = 0;

		for (int j = 0; j < n; j++)
		{
			if (vec[i][j] == true)
			{
				newMax++;
			}
		}

		if (newMax > maxx)
		{
			maxx = newMax;
			indx = i;
		}
	}

	OPACHKI( indx );

	cout << pow( 2.0, step );

	return 0;
}


#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

typedef unsigned int uint;
typedef long long ll;

using namespace std;

int main()
{

#ifdef _DEBUG
	FILE* ci;
	FILE* co;

	freopen_s( &ci, "input.txt", "r", stdin );
	freopen_s( &co, "output.txt", "w", stdout );
#endif

	int n, m;

	cin >> n >> m;

	cout << int(pow( 2.0, m ));

	return 0;
}


#include <iostream>
#include <vector>
#include <string>
#include <cmath>

typedef unsigned int uint;
typedef long long ll;

using namespace std;

int n = 0, m = 0, step = 0;
vector< vector< bool>> vec;

int WMaxActiv(int x)
{
	int maxx = 0; int indx = -1;

	for (int i = 0; i < n; i++)
	{
		if (vec[x][i] == false) continue;
		if (indx == -1) indx = i;

		int newMax = 0;

		for (int j = 0; j < n; j++)
		{
			if (vec[i][j] == true && vec[x][j] == true)
			{
				newMax++;
			}
		}

		if (newMax > maxx)
		{
			maxx = newMax;
			indx = i;
		}
	}

	return indx;
}

void OPACHKI(int x)
{
	while (true)
	{
		int c = WMaxActiv( x );

		if (c == -1) return;
		else
		{
			vec[x][c] = false;
			vec[c][x] = false;
			step++;
			OPACHKI( c );
		}
	}
}

int main()
{
	/*FILE* ci;
	FILE* co;

	freopen_s( &ci, "input.txt", "r", stdin );
	freopen_s( &co, "output.txt", "w", stdout );*/

	cin >> n >> m;

	if (n == 1)
	{
		cout << "1";

		return 0;
	}

	vec.resize( n );

	for (int i = 0; i < n; i++)
	{
		vec[i].resize( n );
	}

	int a, b;
	for (int i = 0; i < m; i++)
	{
		cin >> a >> b;

		vec[a-1][b-1] = true;
		vec[b-1][a-1] = true;
	}

	int maxx = 0; int indx = -1;

	for (int i = 0; i < n; i++)
	{
		int newMax = 0;

		for (int j = 0; j < n; j++)
		{
			if (vec[i][j] == true)
			{
				newMax++;
			}
		}

		if (newMax > maxx)
		{
			maxx = newMax;
			indx = i;
		}
	}

	OPACHKI( indx );

	cout << pow( 2.0, step );

	return 0;
}


#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <cmath>
#include <queue>
#include <memory>
#include <functional>
#include <set>

typedef unsigned int uint;
typedef long long ll;

using namespace std;

const int INF = 1e+9;

int const MAX = 100;

int n, m, answer = 1;
bool used[MAX];
vector< int> g[MAX];

void Dfs( int x )
{
	used[x] = true;
	answer *= 2;

	for (vector< int>::iterator it = g[x].begin(); it != g[x].end(); ++it)
	{
		if (!used[*it])
		{
			Dfs( *it );
		}
	}
}

int main( )
{
	FILE* ci;
	FILE* co;

#ifdef _DEBUG
	freopen_s( &ci, "input.txt", "r", stdin );
	freopen_s( &co, "output.txt", "w", stdout );
//#else
//	freopen_s( &ci, "island2.in", "r", stdin );
//	freopen_s( &co, "island2.out", "w", stdout );
#endif

	cin >> n >> m;

	int a, b;
	for (int i = 0; i < m; ++i)
	{
		cin >> a >> b;
		--a; --b;
		g[a].push_back( b );
		g[b].push_back( a );
	}

	for (int i = 0; i < n; ++i)
	{
		if (!used[i])
		{
			Dfs( i );
			answer /= 2;
		}
	}

	cout << answer << endl;
}


#include <iostream>

using namespace std;

int main( )
{
    int n, m;
    cin >> n >> m;

    cout << pow(2.0, n - m);

    return 0;
}


#include<iostream>
#include<vector>

using namespace std;

int S[55], indexS[55];
vector<int> cnt(55);

int find_root(int x);
long long int power2(int x) {
    if(x==0) return 1;
    else return 2*power2(x-1);
}

long long int max(long long int a, long long int b) { return a>b?a:b; }

int main() {

    int N,M;
    long long int ans=1;

    cin>>N>>M;
    for(int i=1 ; i<=N ; i++) S[i]=i;
    for(int i=0 ; i<M ; i++) {
        int u,v;
        cin>>u>>v;
        if(find_root(u)!=find_root(v))
            S[v]=u;
    }

    for(int i=1 ; i<=N ; i++)
        indexS[i]=find_root(i);
    for(int i=1 ; i<=N ; i++)
        cnt[indexS[i]]++;
    for(int i=1 ; i<=N ; i++)
        if(cnt[i]>0) ans=max(ans,power2(cnt[i]-1));

    cout<<ans<<endl;
    return 0;
}

int find_root(int x) {
    if(x==S[x]) return x;
    else return find_root(S[x]);
}


#include<iostream>
#include<vector>

using namespace std;

int S[55], indexS[55];
vector<int> cnt(55);

int find_root(int x);
int power2(int x) {
    if(x==0) return 1;
    else return 2*power2(x-1);
}

int main() {

    int N,M,ans=1;

    cin>>N>>M;
    for(int i=1 ; i<=N ; i++) S[i]=i;
    for(int i=0 ; i<M ; i++) {
        int u,v;
        cin>>u>>v;
        if(find_root(u)!=find_root(v))
        S[v]=u;
    }

    for(int i=1 ; i<=N ; i++)
        indexS[i]=find_root(i);
    for(int i=1 ; i<=N ; i++)
        cnt[indexS[i]]++;
    for(int i=1 ; i<=N ; i++)
        if(cnt[i]>0) ans*=power2(cnt[i]-1);

    cout<<ans<<endl;
    return 0;
}

int find_root(int x) {
    if(x==S[x]) return x;
    else return find_root(S[x]);
}


#include<iostream>
#include<vector>

using namespace std;

int S[55], indexS[55];
vector<int> cnt(55);

int find_root(int x);

int main() {

    int N,M;
    long long int ans=1;

    cin>>N>>M;
    for(int i=1 ; i<=N ; i++) S[i]=i;
    for(int i=0 ; i<M ; i++) {
        int u,v;
        cin>>u>>v;
        if(find_root(u)!=find_root(v))
            S[find_root(v)]=find_root(u);
    }

    for(int i=1 ; i<=N ; i++)
        indexS[i]=find_root(i);
    for(int i=1 ; i<=N ; i++)
        cnt[indexS[i]]++;
    for(int i=1 ; i<=N ; i++)
        if(cnt[i]>0) ans=ans<<(cnt[i]-1);

    cout<<ans<<endl;
    return 0;
}

int find_root(int x) {
    if(x==S[x]) return x;
    else return find_root(S[x]);
}


#include<iostream>
#include<vector>

using namespace std;

int S[55], indexS[55];
vector<int> cnt(55);

int find_root(int x);
long long int power2(int x) {
    if(x==0) return 1;
    else return 2*power2(x-1);
}

int main() {

    long long int N,M,ans=1;

    cin>>N>>M;
    for(int i=1 ; i<=N ; i++) S[i]=i;
    for(int i=0 ; i<M ; i++) {
        int u,v;
        cin>>u>>v;
        if(find_root(u)!=find_root(v))
        S[v]=u;
    }

    for(int i=1 ; i<=N ; i++)
        indexS[i]=find_root(i);
    for(int i=1 ; i<=N ; i++)
        cnt[indexS[i]]++;
    for(int i=1 ; i<=N ; i++)
        if(cnt[i]>0) ans*=power2(cnt[i]-1);

    cout<<ans<<endl;
    return 0;
}

int find_root(int x) {
    if(x==S[x]) return x;
    else return find_root(S[x]);
}


#include<iostream>
#include<vector>

using namespace std;

int S[55], indexS[55];
vector<int> cnt(55);

int find_root(int x);
int power2(int x) {
    if(x==0) return 1;
    else return 2*power2(x-1);
}

int main() {

    int N,M,ans=1;

    cin>>N>>M;
    for(int i=1 ; i<=N ; i++) S[i]=i;
    for(int i=0 ; i<M ; i++) {
        int u,v;
        cin>>u>>v;
        S[v]=u;
    }

    for(int i=1 ; i<=N ; i++)
        indexS[i]=find_root(i);
    for(int i=1 ; i<=N ; i++)
        cnt[indexS[i]]++;
    for(int i=1 ; i<=N ; i++)
        if(cnt[i]>0) ans*=power2(cnt[i]-1);

    cout<<ans<<endl;
    return 0;
}

int find_root(int x) {
    if(x==S[x]) return x;
    else return find_root(S[x]);
}


#include<iostream>
#include<vector>

using namespace std;

int S[55], indexS[55];
vector<int> cnt(55);

int find_root(int x);
long long int power2(int x) {
    if(x==0) return 1;
    else return 2*power2(x-1);
}

long long int max(long long int a, long long int b) { return a>b?a:b; }

int main() {

    int N,M;
    long long int ans=1;

    cin>>N>>M;
    for(int i=1 ; i<=N ; i++) S[i]=i;
    for(int i=0 ; i<M ; i++) {
        int u,v;
        cin>>u>>v;
        if(find_root(u)!=find_root(v))
            S[find_root(v)]=find_root(u);
    }

    for(int i=1 ; i<=N ; i++)
        indexS[i]=find_root(i);
    for(int i=1 ; i<=N ; i++)
        cnt[indexS[i]]++;
    for(int i=1 ; i<=N ; i++)
        if(cnt[i]>0) ans=max(ans,power2(cnt[i]-1));

    cout<<ans<<endl;
    return 0;
}

int find_root(int x) {
    if(x==S[x]) return x;
    else return find_root(S[x]);
}


#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cctype>
#include<cstdlib>
#include<algorithm>
#include<bitset>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<map>
#include<set>
#include<stack>
#include<cmath>
#include<sstream>
#include<fstream>
#include<iomanip>
#include<ctime>
#include<complex>
using namespace std;
#define M_PI 3.141592653589793238
#define EPS 1e-9
#define LINF 1e30  //long long int
#define IINF 1000000000  //int
#define CP complex<long double>
#define REP(i,a,b) for(i=a;i<b;i++)
#define rep(i,n) REP(i,0,n)
static const int dx[] = { 1, 0, -1, 0 }, dy[] = { 0, -1, 0, 1 };
long double ccw(long double kari, long double kari1, long double kari2, long double kari3){  //内積
    return kari*kari3 - kari1*kari2;
}
long long int oneday(int year, int month, int day){  //1年1月1日からの、経過日数
    return 365 * year + (year / 4) - (year / 100) + (year / 400) + (306 * (month + 1) / 10) + day - 429;
}
long long int ppow(int a1, int b1){  //a^b
    long long int rr = a1;
    long long int r = 1;
    while (b1>0){
        if (b1 & 1){
            r *= rr;
        }
        rr *= rr;
        b1 >>= 1;
    }
    return r;
}
/*宣言*/
#define MAX_N 51
bool flag[MAX_N];
vector<vector<int> > v(MAX_N);
long long int ans = 0;
int n = 0;
int m = 0;
long long int kari = 0;
void dfs(int b){
    for (int j = 0; j < v[b].size(); j++){
        if (flag[v[b][j]] == 0){
            kari *= 2;
            flag[v[b][j]] = 1;
            dfs(v[b][j]);
        }
    }
    return;
}
int main(){
    ans = 1;
    cin >> n >> m;
    for (int i = 1; i <= m; i++){
        int kari = 0;
        int kari1 = 0;
        cin >> kari >> kari1;
        v[kari].push_back(kari1);
        v[kari1].push_back(kari);
    }
    for (int i = 1; i <= n; i++){
        if (flag[i] == 0){
            flag[i] = 1;
            kari = 1;
            dfs(i);
            if (kari != 1){
                ans *= kari;
            }
        }
    }
    if (ans == 0){
        cout << 1 << endl;
    }
    else{
        cout << ans<< endl;
    }
    return 0;
}


#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cctype>
#include<cstdlib>
#include<algorithm>
#include<bitset>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<map>
#include<set>
#include<stack>
#include<cmath>
#include<sstream>
#include<fstream>
#include<iomanip>
#include<ctime>
#include<complex>
using namespace std;
#define M_PI 3.141592653589793238
#define EPS 1e-9
#define LINF 1e30  //long long int
#define IINF 1000000000  //int
#define CP complex<long double>
#define REP(i,a,b) for(i=a;i<b;i++)
#define rep(i,n) REP(i,0,n)
static const int dx[] = { 1, 0, -1, 0 }, dy[] = { 0, -1, 0, 1 };
long double ccw(long double kari, long double kari1, long double kari2, long double kari3){  //内積
    return kari*kari3 - kari1*kari2;
}
long long int oneday(int year, int month, int day){  //1年1月1日からの、経過日数
    return 365 * year + (year / 4) - (year / 100) + (year / 400) + (306 * (month + 1) / 10) + day - 429;
}
long long int ppow(int a1, int b1){  //a^b
    long long int rr = a1;
    long long int r = 1;
    while (b1>0){
        if (b1 & 1){
            r *= rr;
        }
        rr *= rr;
        b1 >>= 1;
    }
    return r;
}
/*宣言*/
#define MAX_N 51
bool flag[MAX_N];
vector<vector<int> > v(MAX_N);
long long int ans = 0;
int n = 0;
int m = 0;
long long int kari = 0;
void dfs(int b){
    for (int j = 0; j < v[b].size(); j++){
        if (flag[v[b][j]] == 0){
            kari *= 2;
            flag[v[b][j]] = 1;
            dfs(v[b][j]);
        }
    }
    return;
}
int main(){
    cin >> n >> m;
    for (int i = 1; i <= m; i++){
        int kari = 0;
        int kari1 = 0;
        cin >> kari >> kari1;
        v[kari].push_back(kari1);
    }
    for (int i = 1; i <= n; i++){
        if (flag[i] == 0){
            flag[i] = 1;
            kari = 1;
            dfs(i);
            if (kari != 1){
                ans += kari;
            }
        }
    }
    if (ans == 0){
        cout << 1 << endl;
    }
    else{
        cout << ans<< endl;
    }
    return 0;
}


#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cctype>
#include<cstdlib>
#include<algorithm>
#include<bitset>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<map>
#include<set>
#include<stack>
#include<cmath>
#include<sstream>
#include<fstream>
#include<iomanip>
#include<ctime>
#include<complex>
using namespace std;
#define M_PI 3.141592653589793238
#define EPS 1e-9
#define LINF 1e30  //long long int
#define IINF 1000000000  //int
#define CP complex<long double>
#define REP(i,a,b) for(i=a;i<b;i++)
#define rep(i,n) REP(i,0,n)
static const int dx[] = { 1, 0, -1, 0 }, dy[] = { 0, -1, 0, 1 };
long double ccw(long double kari, long double kari1, long double kari2, long double kari3){  //内積
    return kari*kari3 - kari1*kari2;
}
long long int oneday(int year, int month, int day){  //1年1月1日からの、経過日数
    return 365 * year + (year / 4) - (year / 100) + (year / 400) + (306 * (month + 1) / 10) + day - 429;
}
long long int ppow(int a1, int b1){  //a^b
    long long int rr = a1;
    long long int r = 1;
    while (b1>0){
        if (b1 & 1){
            r *= rr;
        }
        rr *= rr;
        b1 >>= 1;
    }
    return r;
}
/*宣言*/
#define MAX_N 51
bool flag[MAX_N];
vector<vector<int> > v(MAX_N);
long long int ans = 0;
int n = 0;
int m = 0;
long long int kari = 0;
void dfs(int b){
    for (int j = 0; j < v[b].size(); j++){
        if (flag[v[b][j]] == 0){
            kari *= 2;
            flag[v[b][j]] = 1;
            dfs(v[b][j]);
        }
    }
    return;
}
int main(){
    cin >> n >> m;
    for (int i = 1; i <= m; i++){
        int kari = 0;
        int kari1 = 0;
        cin >> kari >> kari1;
        v[kari].push_back(kari1);
        v[kari1].push_back(kari);
    }
    for (int i = 1; i <= n; i++){
        if (flag[i] == 0){
            flag[i] = 1;
            kari = 1;
            dfs(i);
            if (kari != 1){
                ans += kari;
            }
        }
    }
    if (ans == 0){
        cout << 1 << endl;
    }
    else{
        cout << ans<< endl;
    }
    return 0;
}


#include <iostream>
using namespace std;

int main()
{
	int mas[52][52] = {{0}}, n1, n2, i, j, n, m, k, dr = 0, ans = 1;
	int temp[52] = {0};
	temp[1] = 1;
	cin >> n >> m;
	bool is = false, lala = true;
	for(i=0; i<m; i++)
	{
		cin >> n1 >> n2;
		mas[n1][n2] = 1;
		mas[n2][n1] = 1;
	}
	/*for(i=0; i<n; i++)
	{
		for(j=0; j<n; j++)
		{ cout << mas[i][j] << " "; }
		cout << endl;
	}*/
	if(m==0)
	{
		cout << "1";
		return 0;
	}
	while(lala==true)
	{
		lala = false;
		is = false;
		for(j=1; j<=n; j++)
		{
			if(temp[j]==2)
			{ is=true; break; }
		}
		if(is==false)
		{
			for(k=1; k<=n; k++)
			{
				if(temp[k]==0)
				{ i = k; break; }
			}
			temp[i] = -1;
			for(k=1; k<=n; k++)
			{
				if(mas[i][k]==1 && temp[k]!=-1)
				{ temp[k] = 2; }
			}
		}
		else
		{
			temp[j] = -1;
			ans *= 2;
			for(k=1; k<=n; k++)
			{
				if(mas[j][k]==1 && temp[k]!=-1)
				{ temp[k] = 2; }
			}
		}

		for(k=1; k<=n; k++)
		{
			if(temp[k]!=-1)
			{ lala = true; }
		}
	}
	cout << ans;
	return 0;
}


#include <iostream>
using namespace std;

int main()
{
	int mas[52][52] = {{0}}, n1, n2, i, j, n, m, k, dr = 0, ans = 1;
	int temp[52] = {0};
	temp[1] = 1;
	cin >> n >> m;
	bool is = false, lala = true;
	for(i=0; i<m; i++)
	{
		cin >> n1 >> n2;
		mas[n1][n2] = 1;
		mas[n2][n1] = 1;
	}
	/*for(i=0; i<n; i++)
	{
		for(j=0; j<n; j++)
		{ cout << mas[i][j] << " "; }
		cout << endl;
	}*/
	while(lala==true)
	{
		lala = false;
		is = false;
		for(j=1; j<=n; j++)
		{
			if(temp[j]==2)
			{ is=true; break; }
		}
		if(is==false)
		{
			for(k=1; k<=n; k++)
			{
				if(temp[k]==0)
				{ i = k; break; }
			}
			temp[i] = -1;
			for(k=1; k<=n; k++)
			{
				if(mas[i][k]==1 && temp[k]!=-1)
				{ temp[k] = 2; }
			}
		}
		else
		{
			temp[j] = -1;
			ans *= 2;
			for(k=1; k<=n; k++)
			{
				if(mas[j][k]==1 && temp[k]!=-1)
				{ temp[k] = 2; }
			}
		}

		for(k=1; k<=n; k++)
		{
			if(temp[k]!=-1)
			{ lala = true; }
		}
	}
	cout << ans;
	return 0;
}


#include <iostream>
using namespace std;

int main()
{
	int mas[52][52] = {{0}}, n1, n2, i, j, n, m, k, dr = 0;
        _int64 ans = 1;
	int temp[52] = {0};
	temp[1] = 1;
	cin >> n >> m;
	bool is = false, lala = true;
	for(i=0; i<m; i++)
	{
		cin >> n1 >> n2;
		mas[n1][n2] = 1;
		mas[n2][n1] = 1;
	}
	/*for(i=0; i<n; i++)
	{
		for(j=0; j<n; j++)
		{ cout << mas[i][j] << " "; }
		cout << endl;
	}*/
	if(m==0)
	{
		cout << "1";
		return 0;
	}
	while(lala==true)
	{
		lala = false;
		is = false;
		for(j=1; j<=n; j++)
		{
			if(temp[j]==2)
			{ is=true; break; }
		}
		if(is==false)
		{
			for(k=1; k<=n; k++)
			{
				if(temp[k]==0)
				{ i = k; break; }
			}
			temp[i] = -1;
			for(k=1; k<=n; k++)
			{
				if(mas[i][k]==1 && temp[k]!=-1)
				{ temp[k] = 2; }
			}
		}
		else
		{
			temp[j] = -1;
			ans *= 2;
			for(k=1; k<=n; k++)
			{
				if(mas[j][k]==1 && temp[k]!=-1)
				{ temp[k] = 2; }
			}
		}

		for(k=1; k<=n; k++)
		{
			if(temp[k]!=-1)
			{ lala = true; }
		}
	}
	cout << ans;
	return 0;
}


#include <iostream>
#include <vector>
#include <queue>
#include <string>
#include <set>

using namespace std;

//ifstream cin("input.txt"); ofstream cout("output.txt");
long long n, m;
vector<vector<int>> A;
vector <int> used;

void dfs(int v) {
	used[v] = 1;
	for (int i = 1; i <= n; i++) {
		if (A[v][i] == 1 && used[i] != 1) {
			dfs(i);
		}
	}
}
long long step(long long a, long long l) {
	if (l == 0) {
		return 1;
	}
	else if (l % 2 == 0) {
		return step(a*a, l / 2);
	}
	else {
		return a*step(a, l - 1);
	}
}
int main(){
	cin >> n >> m;
	A.resize(n + 1, vector<int>(n+1));
	used.resize(n + 1);
	for (int i = 0; i < m; i++) {
		int x, y;
		cin >> x >> y;
		A[x][y] = 1;
		A[y][x] = 1;
	}
	long long k = 0;
	for (int i = 1; i <= n; i++) {
		if (used[i] != 1) {
			dfs(i);
			k++;
		}
	}
	cout << step(2, n-k);
	return 0;
}


#include <fstream>
#include <vector>
#include <queue>
#include <string>
#include <set>

using namespace std;

ifstream cin("input.txt"); ofstream cout("output.txt");
long long n, m;
vector<vector<int>> A;
vector <int> used;

void dfs(int v) {
	used[v] = 1;
	for (int i = 1; i <= n; i++) {
		if (A[v][i] == 1 && used[i] != 1) {
			dfs(i);
		}
	}
}
long long step(long long a, long long l) {
	if (l == 0) {
		return 1;
	}
	else if (l % 2 == 0) {
		return step(a*a, l / 2);
	}
	else {
		return a*step(a, l - 1);
	}
}
int main(){
	cin >> n >> m;
	A.resize(n + 1, vector<int>(n+1));
	used.resize(n + 1);
	for (int i = 0; i < m; i++) {
		int x, y;
		cin >> x >> y;
		A[x][y] = 1;
		A[y][x] = 1;
	}
	long long k = 0;
	for (int i = 1; i <= n; i++) {
		if (used[i] != 1) {
			dfs(i);
			k++;
		}
	}
	cout << step(2, n-k);
	return 0;
}


#include <iostream>
#include <vector>
#include <queue>
#include <string>
#include <set>

using namespace std;

//ifstream cin("input.txt"); ofstream cout("output.txt");
int n, m;
vector<vector<int>> A;
vector <int> used;

void dfs(int v) {
	used[v] = 1;
	for (int i = 1; i <= n; i++) {
		if (A[v][i] == 1 && used[i] != 1) {
			dfs(i);
		}
	}
}
long long step(int a, int l) {
	if (l == 0) {
		return 1;
	}
	else if (l % 2 == 0) {
		return step(a*a, l / 2);
	}
	else {
		return a*step(a, l - 1);
	}
}
int main(){
	cin >> n >> m;
	A.resize(n + 1, vector<int>(n+1));
	used.resize(n + 1);
	for (int i = 0; i < m; i++) {
		int x, y;
		cin >> x >> y;
		A[x][y] = 1;
		A[y][x] = 1;
	}
	int k = 0;
	for (int i = 1; i <= n; i++) {
		if (used[i] != 1) {
			dfs(i);
			k++;
		}
	}
	cout << step(2, n - k);
	return 0;
}


#include<iostream>
#include<vector>
#include<utility>
using namespace std;
vector<int> adj[10010];
int vis[10010]={0};
int c=0;
void dfs(int z)
{
    if(vis[z]) return;
    vis[z]=1;

    for(int i=0 ;i<adj[z].size();i++)
    {
        int p= adj[z][i];
        dfs(p);
    }
    return ;

}
int main()
{
    int n,m,x,y;
    cin >>n>>m;
    for(int k=0;k<m;k++)
    {

        cin>>x>>y;

        for (int ii=0; ii<10010; ii++)
            (vis[ii] = 0);

        adj[x].push_back(y);
        adj[y].push_back(x);
    }
    long long ans = (1LL << n);
        for(int i=0;i<n;i++)
        {

            if(!vis[i])
            {
                dfs(i);
                ans /= 2;
            }

        }
        if(m==0)cout<<1<<endl;
        else
        cout<<ans*2<<endl;

    return 0;
}


#include<iostream>
#include<vector>

#include<utility>
using namespace std;
vector<int> adj[60];
int vis[60];
int c;
int n,m,x,y;
void dfs(int z)
{
    if(vis[z]) return;
    vis[z]=1;
    for(int i=0 ;i<adj[z].size();i++)
    {
        int p= adj[z][i];
        dfs(p);
    }
    return ;
}
int main()
{
    cin >>n>>m;
    for (int ii=0; ii<60; ii++)
            (vis[ii] = 0);
    for(int k=0;k<m;k++)
    {
        cin>>x>>y;
        adj[x-1].push_back(y-1);
        adj[y-1].push_back(x-1);
    }

    for(int i=0;i<n;i++)
        if(!vis[i])
            {dfs(i);c++;}
//  cout<<c;
    cout<<(1LL<<(n-c)) <<endl;

    return 0;
}


#include <iostream>
#include <cmath>
using namespace std;

int main(){
    int n,m,x,y;
    cin >>n>>m;
    for(int k=0;k<m;k++)
    {

        cin>>x>>y;
    }
    cout<<1* pow((double)2.0,double(m));
    return 0;
}


#include<iostream>
#include<vector>
#include<utility>
using namespace std;
vector<int> adj[10010];
int vis[10010]={0};
int c=0;
void dfs(int z)
{
    if(vis[z]) return;
    vis[z]=1;

    for(int i=0 ;i<adj[z].size();i++)
    {
        int p= adj[z][i];
        dfs(p);
    }
    return ;

}
int main()
{
    int n,m,x,y,c;
    cin >>n>>m;
    for(int k=0;k<m;k++)
    {

        cin>>x>>y;

        for (int ii=0; ii<10010; ii++)
            (vis[ii] = 0);

        adj[x].push_back(y);
        adj[y].push_back(x);
    }

        for(int i=0;i<n;i++)
        {

            if(!vis[i])
            {
                dfs(i);
                c++;
            }

        }

        cout<<(1LL<<(n-c)) <<endl;

    return 0;
}


#include<iostream>
#include<vector>
#include<bits/stdc++.h>
#include<utility>
using namespace std;
vector<int> adj[60];
int vis[60];
int c;
int n,m,x,y;
void dfs(int z)
{
    if(vis[z]) return;
    vis[z]=1;
    for(int i=0 ;i<adj[z].size();i++)
    {
        int p= adj[z][i];
        dfs(p);
    }
    return ;
}
int main()
{
    cin >>n>>m;
    for (int ii=0; ii<60; ii++)
            (vis[ii] = 0);
    for(int k=0;k<m;k++)
    {
        cin>>x>>y;
        adj[x-1].push_back(y-1);
        adj[y-1].push_back(x-1);
    }

    for(int i=0;i<n;i++)
        if(!vis[i])
            {dfs(i);c++;}
//  cout<<c;
    cout<<(1LL<<(n-c)) <<endl;

    return 0;
}


#include<iostream>
#include<cstring>
using namespace std;
int par[100];
int rank[100];
void init(int s)
{
	for(int i=1;i<=s;i++)
	{
		par[i]=i;
		rank[i]=0;
	}
}
int find(int x)
{
	if(par[x]==x)
	{
		return x;
	}
	else
	{
		return par[x]=find(par[x]);
	}
}
void unite(int x,int y)
{
	x=find(x);
	y=find(y);
	if(x==y)
		return;
	if(rank[x]<rank[y])
	{
		par[x]=y;
	}
	else
	{
		par[y]=x;
		if(rank[x]==rank[y])
			rank[x]++;
	}
}
bool same(int x,int y)
{
	return find(x)==find(y);
}
int main()
{
	int n,m,a,b,r,num=0;
	int z[100];
	long long res=1;
	memset(z,0,100);
	cin>>n>>m;
	for(int u=1;u<=n;u++)
	z[u]=u;
	init(n);
	for(int k=0;k<m;k++)
	{
		cin>>a>>b;
		unite(a,b);
	}
	for(int p=1;p<=n;p++)
	{
		r=1;
		if(z[1]!=0)
		{
			for(int q=2;q<=n+1;q++)
			{
				if(same(z[q],z[1])==0)
				{
					z[r]=z[q];
					r++;
				}
			}
			num++;
		}
	}
	for(int t=1;t<=n-num;t++)
		res*=2;
		cout<<res;
		return 0;
}


#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int par[1000];
int rank1[1000];
void init(int n)
{
	for(int i=1;i<=n;i++)
	{
		par[i]=i;
		rank1[i]=0;
	}
}
int find(int x)
{
	if(par[x]==x)
	{
		return x;
	}
	else
	{
		return par[x]=find(par[x]);
	}
}
void unite(int x,int y)
{
	x=find(x);
	y=find(y);
	if(x==y)
		return;
	if(rank1[x]<rank1[y])
	{
		par[x]=y;
	}
	else
	{
		par[y]=x;
		if(rank1[x]==rank1[y])
			rank1[x]++;
	}
}
bool same(int x,int y)
{
	return find(x)==find(y);
}
int main()
{
	int n,m,a,b,r,num=0;
	int z[1000];
	long long res=1;
	memset(z,0,sizeof(z));
	cin>>n>>m;
	for(int u=1;u<=n;u++)
	z[u]=u;
	init(n);
	for(int k=0;k<m;k++)
	{
		cin>>a>>b;
		unite(a,b);
	}
	for(int p=1;p<=n;p++)
	{
		z[0]=z[1];
		r=1;
		if(z[1]!=0)
		{
			for(int q=2;q<=n+1;q++)
			{
				if(!same(z[0],z[q]))
				{
					z[r]=z[q];
					r++;
				}
			}
			num++;
		}
	}
	for(int t=1;t<=n-num;t++)
		res*=2;
		cout<<res;
		return 0;
}


#include<iostream>
#include<cstring>
using namespace std;
int par[100];
int rank[100];
void init(int n)
{
	for(int i=1;i<=n;i++)
	{
		par[i]=i;
		rank[i]=0;
	}
}
int find(int x)
{
	if(par[x]==x)
	{
		return x;
	}
	else
	{
		return par[x]=find(par[x]);
	}
}
void unite(int x,int y)
{
	x=find(x);
	y=find(y);
	if(x==y)
		return;
	if(rank[x]<rank[y])
	{
		par[x]=y;
	}
	else
	{
		par[y]=x;
		if(rank[x]==rank[y])
			rank[x]++;
	}
}
bool same(int x,int y)
{
	return find(x)==find(y);
}
int main()
{
	int n,m,a,b,r,num=0;
	int z[100];
	long long res=1;
	memset(z,0,100);
	cin>>n>>m;
	for(int u=1;u<=n;u++)
	z[u]=u;
	init(n);
	for(int k=0;k<m;k++)
	{
		cin>>a>>b;
		unite(a,b);
	}
	for(int p=1;p<=n;p++)
	{
		r=1;
		if(z[1]!=0)
		{
			for(int q=2;q<=n+1;q++)
			{
				if(same(z[q],z[1])==0)
				{
					z[r]=z[q];
					r++;
				}
			}
			num++;
		}
	}
	for(int t=1;t<=n-num;t++)
		res*=2;
		cout<<res;
	return 0;
}


#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int par[1000];
int rank1[1000];
void init(int s)
{
	for(int i=1;i<=s;i++)
	{
		par[i]=i;
		rank1[i]=0;
	}
}
int find(int x)
{
	if(par[x]==x)
	{
		return x;
	}
	else
	{
		return par[x]=find(par[x]);
	}
}
void unite(int x,int y)
{
	x=find(x);
	y=find(y);
	if(x==y)
		return;
	if(rank1[x]<rank1[y])
	{
		par[x]=y;
	}
	else
	{
		par[y]=x;
		if(rank1[x]==rank1[y])
			rank1[x]++;
	}
}
bool same(int x,int y)
{
	return find(x)==find(y);
}
int main()
{
	int n,m,a,b,r,num=0;
	int z[1000];
	long long res=1;
	memset(z,0,sizeof(z));
	cin>>n>>m;
	for(int u=1;u<=n;u++)
	z[u]=u;
	init(n);
	for(int k=0;k<m;k++)
	{
		cin>>a>>b;
		unite(a,b);
	}
	for(int p=1;p<=n;p++)
	{
		r=1;
		if(z[1]!=0)
		{
			for(int q=2;q<=n+1;q++)
			{
				if(same(z[q],z[1])==0)
				{
					z[r]=z[q];
					r++;
				}
			}
			num++;
		}
	}
	for(int t=1;t<=n-num;t++)
		res*=2;
		cout<<res;
		return 0;
}


#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <ctype.h>
#include <math.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
#define N 55
int father[N];
int n,m;

int find(int x){
	int r=x;
	while(father[r] != r){
		r = father[r];
	}
	//int i = x;
	//int k;
	//while(i != r){
		//k = father[i];
		//father[i] = r;
		//i = k;
	//}

	return r;
}

int main(){
	int i;
	int a,b;
	int ans;
	int sum;

	while(~scanf("%d%d",&n,&m)){
		memset(father,0,sizeof(father));
		for(i=1;i<=n;i++)
			father[i] = i;
		sum = 0;
		ans = 1;
		for(i=1;i<=m;i++){
			scanf("%d%d",&a,&b);
			int f1 = find(father[a]);
			int f2 = find(father[b]);
			if(f1 != f2){
				father[f1] = f2;
			}
		}
		for(i=1;i<=n;i++){
			if(father[i] != i)
				sum++;
		}
		for(i=1;i<=sum;i++)
			ans = ans*2;
		printf("%d\n",ans);
	}

	return 0;
}


#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <ctype.h>
#include <math.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
#define N 55
int father[N];
int n,m;

int find(int x){
	int r=x;
	while(father[r] != r){
		r = father[r];
	}
	int i = x;
	int k;
	while(i != r){
		k = father[i];
		father[i] = r;
		i = x;
	}

	return r;
}

int main(){
	int i;
	int a,b;
	int ans;
	int sum;

	while(~scanf("%d%d",&n,&m)){
		memset(father,0,sizeof(father));
		for(i=1;i<=n;i++)
			father[i] = i;
		sum = 0;
		ans = 1;
		for(i=1;i<=m;i++){
			scanf("%d%d",&a,&b);
			int f1 = find(father[a]);
			int f2 = find(father[b]);
			if(f1 != f2){
				father[f1] = f2;
			}
		}
		for(i=1;i<=n;i++){
			if(father[i] != i)
				sum++;
		}
		for(i=1;i<=sum;i++)
			ans = ans*2;
		printf("%d\n",ans);
	}

	return 0;
}


#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
#define N 55
int mark[N][N];

int main(){
    int n,m;
    int num[N];
    int a,b;
    int i;

    while(~scanf("%d%d",&n,&m)){
        memset(num,0,sizeof(num));
        memset(mark,0,sizeof(mark));
        for(i=0;i<m;i++){
            scanf("%d%d",&a,&b);
            mark[a][b] = 1;
            num[a]++;
            num[b]++;
        }
        int sum=1;
        sort(num,num+n);
        for(i=n-1;i>=1;i--){
            if(num[n] != 0){
                sum = sum*2;
            }

        }
        printf("%d\n",sum);
    }

    return 0;
}


#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <ctype.h>
#include <math.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
#define N 55
int father[N];
int n,m;

int find(int x){
	int r=x;
	while(father[r] != r){
		r = father[r];
	}
	int i = x;
	int k;
	while(i != r){
		k = father[i];
		father[i] = r;
		i = k;
	}

	return r;
}

int main(){
	int i;
	int a,b;
	int ans;
	int sum;

	while(~scanf("%d%d",&n,&m)){
		memset(father,0,sizeof(father));
		for(i=1;i<=n;i++)
			father[i] = i;
		sum = 0;
		ans = 1;
		for(i=1;i<=m;i++){
			scanf("%d%d",&a,&b);
			int f1 = find(father[a]);
			int f2 = find(father[b]);
			if(f1 != f2){
				father[f1] = f2;
			}
		}
		for(i=1;i<=n;i++){
			if(father[i] != i)
				sum++;
		}
		for(i=1;i<=sum;i++)
			ans = ans*2;
		printf("%d\n",ans);
	}

	return 0;
}


#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <ctype.h>
#include <math.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
#define N 55
int father[N];
int n,m;

int find(int x){
	int r=x;
	while(father[r] != r){
		r = father[r];
	}
	int i = x;
	int k;
	while(i != r){
		k = father[i];
		father[i] = r;
		i = k;
	}

	return r;
}

int main(){
	int i;
	int a,b;
	__int64 ans;
	int sum;

	while(~scanf("%d%d",&n,&m)){
		memset(father,0,sizeof(father));
		for(i=1;i<=n;i++)
			father[i] = i;
		sum = 0;
		ans = 1;
		for(i=1;i<=m;i++){
			scanf("%d%d",&a,&b);
			int f1 = find(father[a]);
			int f2 = find(father[b]);
			if(f1 != f2){
				father[f1] = f2;
			}
		}
		for(i=1;i<=n;i++){
			if(father[i] != i)
				sum++;
		}
		for(i=1;i<=sum;i++)
			ans = ans*2;
		printf("%I64d\n",ans);
	}

	return 0;
}


#include <iostream>
#include <stdio.h>
#include <vector>
#include <set>
#include <string>
#include <queue>
#include <algorithm>
#include <math.h>
#include <stack>
#include <sstream>
using namespace std;
typedef long long ll;
typedef unsigned U;
typedef vector<int> vi;
typedef pair<int, int> ii;
typedef vector<pair<int, int>> vii;
#define REP(i,s,n) for(int i=s;i<n;i++)

int main()
{
    int n, m; cin >> n >> m;
    int a, b;
    REP(i, 0, m) cin >> a >> b;
    int p = min(n-1, m);
    int res = 1;
    res=res << p;
    cout << res;
}


#include <iostream>
#include <stdio.h>
#include <vector>
#include <set>
#include <string>
#include <queue>
#include <algorithm>
#include <math.h>
#include <stack>
#include <sstream>
using namespace std;
typedef long long ll;
typedef unsigned U;
typedef vector<int> vi;
typedef pair<int, int> ii;
typedef vector<pair<int, int>> vii;
#define REP(i,s,n) for(int i=s;i<n;i++)

int main()
{
    int n, m; cin >> n >> m;
    int a, b;
    REP(i, 0, m) cin >> a >> b;
    int p = min(n, m);
    int res = 1;
    res=res << p;
    cout << res;
}


#include <iostream>
#include <stdio.h>
#include <vector>
#include <set>
#include <string>
#include <queue>
#include <algorithm>
#include <math.h>
#include <stack>
#include <sstream>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef vector<int> vi;
typedef pair<int, int> ii;
typedef vector<pair<int, int>> vii;
#define REP(i,s,n) for(int i=s;i<n;i++)

int parent[101];
int size[101];

void dsu_init(int n){
    memset(size, 0, sizeof size);
    REP(i, 1, n + 1) parent[i] = i;
}

int dsu_root(int x){ return x == parent[x] ? x : dsu_root(parent[x]); }
bool dsu_same_set(int x, int y){ return dsu_root(x) == dsu_root(y); }
void dsu_union_set(int x, int y){
    x = dsu_root(x); y = dsu_root(y);
    if (x != y){
        if (x > y) swap(x, y);
        parent[x] = y;
        size[y] += size[x] + 1;
        size[x] = 0;
    }
}

ULL power(int x, int y){
    if (y == 0) return 1;
    return x * power(x, y - 1);
}
int main()

{
    //freopen("testcases.txt", "r", stdin);
    int n, m; cin >> n >> m;
    dsu_init(n);
    REP(i, 1, m + 1){
        int a, b; cin >> a >> b;
        dsu_union_set(a, b);
    }
    ULL res = 0;
    REP(i, 1, n + 1){
        res += size[i];
    }
    cout<< power(2, res);
}


#include <iostream>
#include <stdio.h>
#include <vector>
#include <set>
#include <string>
#include <queue>
#include <algorithm>
#include <math.h>
#include <stack>
#include <sstream>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef vector<int> vi;
typedef pair<int, int> ii;
typedef vector<pair<int, int>> vii;
#define REP(i,s,n) for(int i=s;i<n;i++)

int parent[101];
int size[101];

void dsu_init(int n){
    memset(size, 0, sizeof size);
    REP(i, 1, n + 1) parent[i] = i;
}

int dsu_root(int x){ return x == parent[x] ? x : dsu_root(parent[x]); }
bool dsu_same_set(int x, int y){ return dsu_root(x) == dsu_root(y); }
void dsu_union_set(int x, int y){
    x = dsu_root(x); y = dsu_root(y);
    if (x != y){
        if (x > y) swap(x, y);
        parent[x] = y;
        size[y] += size[x] + 1;
        size[x] = 0;
    }
}
int main()

{
    freopen("testcases.txt", "r", stdin);
    int n, m; cin >> n >> m;
    dsu_init(n);
    REP(i, 1, m + 1){
        int a, b; cin >> a >> b;
        dsu_union_set(a, b);
    }
    ULL res = 0;
    REP(i, 1, n + 1){
        res += size[i];
    }
    res = pow(2, res);
    cout << res;
}


#include <iostream>
#include <stdio.h>
#include <vector>
#include <set>
#include <string>
#include <queue>
#include <algorithm>
#include <math.h>
#include <stack>
#include <sstream>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef vector<int> vi;
typedef pair<int, int> ii;
typedef vector<pair<int, int>> vii;
#define REP(i,s,n) for(int i=s;i<n;i++)

int parent[101];
int size[101];

void dsu_init(int n){
    memset(size, 0, sizeof size);
    REP(i, 1, n + 1) parent[i] = i;
}

int dsu_root(int x){ return x == parent[x] ? x : dsu_root(parent[x]); }
bool dsu_same_set(int x, int y){ return dsu_root(x) == dsu_root(y); }
void dsu_union_set(int x, int y){
    x = dsu_root(x); y = dsu_root(y);
    if (x != y){
        if (x > y) swap(x, y);
        parent[x] = y;
        size[y] += size[x] + 1;
        size[x] = 0;
    }
}

int main()

{
    //freopen("testcases.txt", "r", stdin);
    int n, m; cin >> n >> m;
    dsu_init(n);
    REP(i, 1, m + 1){
        int a, b; cin >> a >> b;
        dsu_union_set(a, b);
    }
    ULL res = 0;
    REP(i, 1, n + 1){
        res += size[i];
    }
    res = 1ULL << res;
    cout << res;
}


#include <iostream>
#include <stdio.h>
#include <vector>
#include <set>
#include <string>
#include <queue>
#include <algorithm>
#include <math.h>
#include <stack>
#include <sstream>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef vector<int> vi;
typedef pair<int, int> ii;
typedef vector<pair<int, int>> vii;
#define REP(i,s,n) for(int i=s;i<n;i++)

int parent[101];
int size[101];

void dsu_init(int n){
    memset(size, 0, sizeof size);
    REP(i, 1, n + 1) parent[i] = i;
}

int dsu_root(int x){ return x == parent[x] ? x : dsu_root(parent[x]); }
bool dsu_same_set(int x, int y){ return dsu_root(x) == dsu_root(y); }
void dsu_union_set(int x, int y){
    x = dsu_root(x); y = dsu_root(y);
    if (x != y){
        if (x > y) swap(x, y);
        parent[x] = y;
        size[y] += size[x] + 1;
        size[x] = 0;
    }
}
int main()

{
    freopen("testcases.txt", "r", stdin);
    int n, m; cin >> n >> m;
    dsu_init(n);
    REP(i, 1, m + 1){
        int a, b; cin >> a >> b;
        dsu_union_set(a, b);
    }
    ULL res = 0;
    REP(i, 1, n + 1){
        res += size[i];
    }
    res = pow((double)2, (double)res);
    cout <<(int) res;
}


#include <iostream>
#include <stdio.h>
#include <vector>
#include <set>
#include <string>
#include <queue>
#include <algorithm>
#include <math.h>
#include <stack>
#include <sstream>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef vector<int> vi;
typedef pair<int, int> ii;
typedef vector<pair<int, int>> vii;
#define REP(i,s,n) for(int i=s;i<n;i++)

int parent[101];
int size[101];

void dsu_init(int n){
    memset(size, 0, sizeof size);
    REP(i, 1, n + 1) parent[i] = i;
}

int dsu_root(int x){ return x == parent[x] ? x : dsu_root(parent[x]); }
bool dsu_same_set(int x, int y){ return dsu_root(x) == dsu_root(y); }
void dsu_union_set(int x, int y){
    x = dsu_root(x); y = dsu_root(y);
    if (x != y){
        if (x > y) swap(x, y);
        parent[x] = y;
        size[y] += size[x] + 1;
        size[x] = 0;
    }
}
int main()
{
    int n, m; cin >> n >> m;
    dsu_init(n);
    REP(i, 1, m + 1){
        int a, b; cin >> a >> b;
        dsu_union_set(a, b);
    }
    ULL res = 0;
    REP(i, 1, n + 1){
        res += size[i];
    }
    res = 1 << res;
    cout << res;
}


#include <iostream>
#include <stdio.h>
#include <vector>
#include <set>
#include <string>
#include <queue>
#include <algorithm>
#include <math.h>
#include <stack>
#include <sstream>
using namespace std;
typedef long long ll;
typedef unsigned U;
typedef vector<int> vi;
typedef pair<int, int> ii;
typedef vector<pair<int, int>> vii;
#define REP(i,s,n) for(int i=s;i<n;i++)

int parent[101];
int size[101];

void dsu_init(int n){
    memset(size, 0, sizeof size);
    REP(i, 1, n + 1) parent[i] = i;
}

int dsu_root(int x){ return x == parent[x] ? x : dsu_root(parent[x]); }
bool dsu_same_set(int x, int y){ return dsu_root(x) == dsu_root(y); }
void dsu_union_set(int x, int y){
    x = dsu_root(x); y = dsu_root(y);
    if (x != y){
        if (x > y) swap(x, y);
        parent[x] = y;
        size[y] += size[x] + 1;
        size[x] = 0;
    }
}
int main()
{
    int n, m; cin >> n >> m;
    dsu_init(n);
    REP(i, 1, m + 1){
        int a, b; cin >> a >> b;
        dsu_union_set(a, b);
    }
    int res = 0;
    REP(i, 1, n + 1){
        res += size[i];
    }
    res = 1 << res;
    cout << res;
}


#include <stdio.h>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <math.h>

int m,n,p[50],q[50];

int step(int n) {
    int s=1;
    for(int i=0;i<n;i++) s*=2;
    return s;
}

int find(int v) {
    if (p[v]==v) return v;
    return (p[v]=find(p[v]));
}

void uni(int v1,int v2) {
    int p1=find(v1);
    int p2=find(v2);
    if (p1!=p2) {
        p[p1]=p2;
        q[p2]+=q[p1];
    }
}

int main(){
    #pragma comment(linker, "/STACK:134217728")
    #ifndef ONLINE_JUDGE
        freopen("input.txt", "rt", stdin);
        freopen("output.txt", "wt", stdout);
    #endif
        int i,j,a,b,k=1;
    scanf("%d%d",&n,&m);
    for(i=0;i<n;i++) {
        p[i]=i;
        q[i]=1;
    }
    for(i=0;i<m;i++) {
        scanf("%d%d",&a,&b);
        uni(a-1,b-1);
    }
    for(i=0;i<n;i++) {
        if (i==p[i]) k*=step(q[i]-1);
    }

    printf("%d",k);

    return 0;
}


#include <stdio.h>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <math.h>

long long int m,n,p[50],q[50];

long long int step(long long int n) {
    long long int s=1;
    for(int i=0;i<n;i++) s*=2;
    return s;
}

long long int find(long long int v) {
    if (p[v]==v) return v;
    return (p[v]=find(p[v]));
}

void uni(long long int v1,long long int v2) {
    long long int p1=find(v1);
    long long int p2=find(v2);
    if (p1!=p2) {
        p[p1]=p2;
        q[p2]+=q[p1];
    }
}

int main(){
    #pragma comment(linker, "/STACK:134217728")
    #ifndef ONLINE_JUDGE
        freopen("input.txt", "rt", stdin);
        freopen("output.txt", "wt", stdout);
    #endif
        long long int i,j,a,b,k=1;
    scanf("%d%d",&n,&m);
    for(i=0;i<n;i++) {
        p[i]=i;
        q[i]=1;
    }
    for(i=0;i<m;i++) {
        scanf("%d%d",&a,&b);
        uni(a-1,b-1);
    }
    for(i=0;i<n;i++) {
        if (i==p[i]) k*=step(q[i]-1);
    }

    printf("%d",k);

    return 0;
}


#include <stdio.h>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <math.h>

long long int m,n,p[50],q[50];

long long int step(long long int n) {
    long long int s=1;
    for(int i=0;i<n;i++) s*=2;
    return s;
}

long long int find(long long int v) {
    if (p[v]==v) return v;
    return (p[v]=find(p[v]));
}

void uni(long long int v1,long long int v2) {
    long long int p1=find(v1);
    long long int p2=find(v2);
    if (p1!=p2) {
        p[p1]=p2;
        q[p2]+=q[p1];
    }
}

int main(){
    #pragma comment(linker, "/STACK:134217728")
    #ifndef ONLINE_JUDGE
        freopen("input.txt", "rt", stdin);
        freopen("output.txt", "wt", stdout);
    #endif
        long long int i,j,a,b,k=1;
    scanf("%d%d",&n,&m);
    for(i=0;i<n;i++) {
        p[i]=i;
        q[i]=1;
    }
    for(i=0;i<m;i++) {
        scanf("%d%d",&a,&b);
        uni(a-1,b-1);
    }
    for(i=0;i<n;i++) {
        if (i==p[i]) k*=step(q[i]-1);
    }

    printf("%I64d",k);

    return 0;
}


#include<iostream>
#include<cstdio>
using namespace std;
int f[51],num[51];
int ff(int son);
void u(int fa,int fb);
int main(){
	int n,m,a,b,i,fa,fb,ans;
	while(scanf("%d%d",&n,&m)!=EOF){
		for(i=1;i<=n;i++){
			f[i]=i;
			num[i]=1;
		}
		for(i=0;i<m;i++){
			scanf("%d%d",&a,&b);
			fa=ff(a);
			fb=ff(b);
			if(fa!=fb)
				u(fa,fb);
		}
		ans=0;
		for(i=1;i<=n;i++)
			ans=ans+num[i]-1;
		printf("%I64d\n",(__int64)1<<ans);
	}
	return 0;
}
int ff(int son){
	int i,temp;
	for(i=son;i!=f[i];i=f[i]);
	while(son!=i){
		temp=f[son];
		f[son]=i;
		son=temp;
	}
	return i;
}
void u(int fa,int fb){
	if(num[fa]<num[fb]){
		f[fa]=fb;
		num[fb]+=num[fa];
	}
	else{
        f[fb]=fa;
		num[fa]+=num[fb];
	}
}


#include<iostream>
#include<cstdio>
using namespace std;
int f[51],num[51];
int ff(int son);
void u(int fa,int fb);
int main(){
	int n,m,a,b,i,fa,fb,ans;
	__int64 x;
	while(scanf("%d%d",&n,&m)!=EOF){
		for(i=1;i<=n;i++){
			f[i]=i;
			num[i]=1;
		}
		for(i=0;i<m;i++){
			scanf("%d%d",&a,&b);
			fa=ff(a);
			fb=ff(b);
			if(fa!=fb)
				u(fa,fb);
		}
		ans=0;
		for(i=1;i<=n;i++)
		   if(f[i]==i)
			ans=ans+num[i]-1;
		x=1;
		printf("%I64d\n",x<<ans);
	}
	return 0;
}
int ff(int son){
	int i,temp;
	for(i=son;i!=f[i];i=f[i]);
	while(son!=i){
		temp=f[son];
		f[son]=i;
		son=temp;
	}
	return i;
}
void u(int fa,int fb){
	if(num[fa]<num[fb]){
		f[fa]=fb;
		num[fb]+=num[fa];
	}
	else{
        f[fb]=fa;
		num[fa]+=num[fb];
	}
}


#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int main(){
	int n,ma[51][51],x,y,vis[51],sum,j,i,out[51],max,m,ext;
   while(scanf("%d%d",&n,&m)!=EOF){
	   memset(ma,0,sizeof(ma));
	   memset(vis,0,sizeof(vis));
       memset(out,0,sizeof(out));
	for(i=0;i<m;i++){
		scanf("%d%d",&x,&y);
		ma[x][y]=ma[y][x]=1;
		out[x]++;
		out[y]++;
    }
	for(sum=i=0;i<n;i++){
	   for(max=-1,j=1;j<=n;j++)
			if(out[j]>max){
			   max=out[j];
			   ext=j;
			}
		if(vis[ext])
			sum++;
		out[ext]=-1;
		for(j=1;j<=n;j++){
			if(ma[ext][j])
			vis[j]++;
			out[j]--;
		}
	}
	printf("%I64d\n",(__int64)(1<<sum));
   }
   return 0;
}


#include<iostream>
#include<cstdio>
using namespace std;
int f[51],num[51];
int ff(int son);
void u(int fa,int fb);
int main(){
	int n,m,a,b,i,fa,fb,ans;
	__int64 x;
	while(scanf("%d%d",&n,&m)!=EOF){
		for(i=1;i<=n;i++){
			f[i]=i;
			num[i]=1;
		}
		for(i=0;i<m;i++){
			scanf("%d%d",&a,&b);
			fa=ff(a);
			fb=ff(b);
			if(fa!=fb)
				u(fa,fb);
		}
		ans=0;
		for(i=1;i<=n;i++)
			ans=ans+num[i]-1;
		x=(1<<ans);
		if(ans>30)
          x=(1<<(ans-30))*(1<<30);
		printf("%I64d\n",x);
	}
	return 0;
}
int ff(int son){
	int i,temp;
	for(i=son;i!=f[i];i=f[i]);
	while(son!=i){
		temp=f[son];
		f[son]=i;
		son=temp;
	}
	return i;
}
void u(int fa,int fb){
	if(num[fa]<num[fb]){
		f[fa]=fb;
		num[fb]+=num[fa];
	}
	else{
        f[fb]=fa;
		num[fa]+=num[fb];
	}
}


#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int main(){
	int n,ma[51][51],x,y,vis[51],sum,j,i,out[51],max,m,ext;
   while(scanf("%d%d",&n,&m)!=EOF){
	   memset(ma,0,sizeof(ma));
	   memset(vis,0,sizeof(vis));
       memset(out,0,sizeof(out));
	for(i=0;i<m;i++){
		scanf("%d%d",&x,&y);
		ma[x][y]=ma[y][x]=1;
		out[x]++;
		out[y]++;
    }
	for(sum=i=0;i<n;i++){
	   for(max=-1,j=1;j<=n;j++)
			if(out[j]>max){
			   max=out[j];
			   ext=j;
			}
		if(vis[ext])
			sum++;
		out[ext]=-1;
		for(j=1;j<=n;j++){
			if(ma[ext][j])
			vis[j]++;
			out[j]--;
		}
	}
	printf("%lld\n",(__int64)(1<<sum));
   }
   return 0;
}


#include<iostream>
#include<algorithm>
using namespace std;
struct node{
	int f,cnt,son[51];
	bool operator<(const node& a){
		return cnt>a.cnt;
	}
};
node p[51];
int main(){
	int n,m,x,y,vis[51],sum,j,i;
   while(scanf("%d%d",&n,&m)!=EOF){
	   for(i=1;i<=n;i++){
		   p[i].f=i;
		   p[i].cnt=0;
		   vis[i]=0;
	   }
	   sum=0;
	for(i=0;i<m;i++){
		scanf("%d%d",&x,&y);
		p[x].son[p[x].cnt++]=y;
        p[y].son[p[y].cnt++]=x;
    }
    sort(p+1,p+n+1);
	for(i=1;i<n+1;i++){
		if(vis[p[i].f])
			sum++;
		for(j=0;j<p[i].cnt;j++){
			y=p[i].son[j];
			vis[y]++;
		}
	}
	printf("%I64d\n",(__int64)(1<<sum));
   }
   return 0;
}


#include<iostream>
#include<cstdio>
using namespace std;
int f[51],num[51];
int ff(int son);
void u(int fa,int fb);
int main(){
	int n,m,a,b,i,fa,fb,ans;
	__int64 x;
	while(scanf("%d%d",&n,&m)!=EOF){
		for(i=1;i<=n;i++){
			f[i]=i;
			num[i]=1;
		}
		for(i=0;i<m;i++){
			scanf("%d%d",&a,&b);
			fa=ff(a);
			fb=ff(b);
			if(fa!=fb)
				u(fa,fb);
		}
		ans=0;
		for(i=1;i<=n;i++)
			ans=ans+num[i]-1;
		x=1;
	    while(ans--)
			x=x*2;
		printf("%I64d\n",x);
	}
	return 0;
}
int ff(int son){
	int i,temp;
	for(i=son;i!=f[i];i=f[i]);
	while(son!=i){
		temp=f[son];
		f[son]=i;
		son=temp;
	}
	return i;
}
void u(int fa,int fb){
	if(num[fa]<num[fb]){
		f[fa]=fb;
		num[fb]+=num[fa];
	}
	else{
        f[fb]=fa;
		num[fa]+=num[fb];
	}
}


#include <iostream>
#include<algorithm>
#include<utility>
#include<vector>

using namespace std;

vector<int>  x[50];
bool z[50];

int main()
{
    unsigned long long s=1;
    int n,m,a,b;
    int i,p,t;
    cin>>n;
    cin>>m;
    for(i=0;i<n;i++) z[i]=false;
    for(i=0;i<m;i++)
    {
        cin>>a;
        cin>>b;
        a--;
        b--;
        x[a].push_back(b);
        x[b].push_back(a);
    }
    bool f;
    z[0]=true;
    p=1;
    t=2;
    while(p!=n)
    {
        t=p;
        a=-1;
        for(i=1;i<n;i++)
        {
            if(z[i]==false)
            {
                for(size_t j=0;j<x[i].size();j++)
                {
                    if(z[x[i][j]]==true)
                    {
                        p++;
                        s*=2;
                        z[i]=true;
                        j=x[i].size();
                    }
                }
                if(f) a=i;
            }
        }
        if(t==p)
        {
            for(i=1;i<n;i++)
            {
                if(!z[i])
                {
                    p++;
                    z[i]=true;
                    break;
                }
            }
        }
    }
    cout<<s;
    return 0;
}


#include <iostream>
#include<algorithm>
#include<utility>
#include<vector>

using namespace std;

bool y[51][51];
int n;

void dfs(int i,int & t)
{
    size_t j;
    for(j=1;j<=n;j++)
    {
        if(y[i][j])
        {
            y[i][j]=false;
            y[j][i]=false;
            int p=t+1;
            dfs(j,p);
            if(p>t) t=p;
            y[i][j]=true;
            y[j][i]=true;
        }
    }
    return;
}

int main()
{
    unsigned long long s=1;
    int m,a,b;
    int p,l;
    int i,j,k;
    cin>>n;
    for(i=1;i<=n;i++)
    for(j=1;j<=n;j++)
    y[i][j]=false;
    cin>>m;
    for(i=0;i<m;i++)
    {
        cin>>a;
        cin>>b;
        y[a][b]=true;
        y[b][a]=true;
    }
    for(i=1;i<=n;i++)
    {
        l=0;
        dfs(i,l);
        if(l>p) p=l;
    }
    for(i=0;i<p;i++) s*=2;
    cout<<s;
    return 0;
}


#include <iostream>
#include<algorithm>
#include<utility>
#include<vector>

using namespace std;

pair<int,vector<int> > x[50];
bool z[50];

int main()
{
    unsigned long long s=1;
    int n,m,a,b;
    int i;
    cin>>n;
    cin>>m;
    for(i=0;i<n;i++)
    {
        z[i]=false;
        x[i].first=0;
        x[i].second.push_back(i);
    }
    for(i=0;i<m;i++)
    {
        cin>>a;
        cin>>b;
        a--;
        b--;
        x[a].first++;
        x[a].second.push_back(b);
        x[b].first++;
        x[b].second.push_back(a);
    }
    sort(x,x+n);
    bool f;
    for(i=0;i<n;i++)
    {
        f=true;
        if(z[x[i].second[0]]) f=false;
        z[x[i].second[0]]=true;
        for(size_t j=1;j<x[i].second.size();j++)
        {
            if(!z[x[i].second[j]]) s=s*2;
            else
            {
                if(f)
                {
                    s=s*2;
                    f=false;
                }
            }
            z[x[i].second[j]]=true;
        }
    }
    cout<<s;
    return 0;
}