#include<bits/stdc++.h>
using namespace std;
#define rep(i,s,t) for (int i=s;i<=t;i++)
#define pi acos(-1)
typedef long long LL;
typedef pair<int,int> PII;
typedef pair<double, double> PDD;
typedef pair<PII, PII> PPP;
typedef pair<PII, int> PPI;
typedef pair<int*, int> PTI;
#define repp(i,s,t) for (int i=s;i>=t;i--)
template<class T> T sqr(T x) {return x*x;}
#define debug(x) cerr<<#x"="<<(x)<<endl;
#define pb(x) push_back(x);
#define ori(x) x-'a'
const int maxn = 3e5;
vector<int> tree[3 * maxn];
int n, m, x, y;
int f[maxn], dist[maxn], U[maxn], V[maxn], sz[maxn];
int tag[3 * maxn];
vector<PTI> restore;
/*int find(int k)
{
	if (f[k] != k)
	{
		int u = f[k];
		f[k] = find(f[k]);
		dist[k] = dist[k] ^ dist[u];
	}
	return f[k];
}*/ // do not compress the path, in this problem you need to recover it..................
inline PII find(int k)
{
	int dk = 0;
	int fk = k;
	while (fk != f[fk])
	{
		dk ^= dist[fk];
		fk = f[fk];
	}
	return PII(fk, dk);
}
void insert(int k, int l, int r, int ll, int rr, int ee)
{
	if (ll > rr) return;
	int mid = (l + r) >> 1;
//	cout << k << " " << l << " " << r << " " << ll << " " << rr << " " << ee << endl;
	if (l == ll && rr == r) 
	{
		tree[k].push_back(ee);
		return ;
	}
	if (rr <= mid) insert(k << 1, l, mid, ll, rr, ee);
	else if (ll > mid) insert(k << 1 | 1, mid + 1, r, ll, rr, ee);
	else
	{
		insert(k << 1, l, mid, ll, mid, ee);
		insert(k << 1 | 1, mid + 1, r, mid + 1, rr, ee);
	}
}
inline void modify(int &a, int b)
{
	restore.push_back(PTI(&a, a));
	a = b;
}
inline int merge(int u, int v)
{
	PII fu = find(u);
	PII fv = find(v);
	if (fu.first == fv.first)
	{
		if (fu.second == fv.second) return 0;
		else return 1;
	}
	else
	{
		if (sz[fu.first] < sz[fv.first]) swap(fu, fv);
		modify(sz[fu.first], sz[fu.first] + sz[fv.first]);
		modify(f[fv.first], fu.first);
		modify(dist[fv.first], fu.second ^ fv.second ^ 1);
	}
	return 1;
}
void solve(int k, int l, int r)
{
	int cur = restore.size();
	int mid = (l + r) >> 1;
	for (int i = 0 ; i < tree[k].size(); i++)
	{
		int u = U[tree[k][i]];
		int v = V[tree[k][i]];
//		cout << i << "  " << tree[k][i] << "  " << u << "  " << v << endl;
//		cout << merge(u, v) << endl;
		if (merge(u, v) == 0)
		{
			tag[k] = 1;
			break;
		}
	}
//	cout << k << " " << l << " " << r << " " << tag[k] << endl;
	if (!tag[k] && l < r)
	{
		solve(k << 1, l, mid);
		solve(k << 1 | 1, mid + 1, r);
	}
	while (restore.size() > cur)
	{
		*(restore.back().first) = restore.back().second;
		restore.pop_back();
	}
}
void gao(int k, int l, int r, int TAG)
{
	TAG = TAG | tag[k];
	tag[k] = 0;
	tree[k].clear();
	int mid = (l + r) >> 1;
	if (l == r)
	{
		printf("%d", 1 - TAG);
		return;
	}
	gao(k << 1, l, mid, TAG);
	gao(k << 1 | 1, mid + 1, r, TAG);	

}
int main()
{
	int testdata;
	scanf("%d",&testdata);
	int cnt = 0;
	while (testdata--)
	{
		++cnt;
		scanf("%d%d",&n,&m);
		rep(i,1,m)
		{
			scanf("%d%d",&x,&y);
			if (x > y) swap(x, y);
			U[i] = x;
			V[i] = y;
			insert(1, 1, n, 1, x-1, i);
			insert(1, 1, n, x+1, y-1, i);
			insert(1, 1, n, y+1, n, i);
		}
		rep(i,1,n) f[i] = i, sz[i] = 1, dist[i] = 0;
		solve(1, 1, n);
		gao(1, 1, n, false);
		puts("");
	}
}

