#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;

const int maxn = 200000 + 10;

typedef pair<int, int> ii;

vector<int> E[maxn];
ii edge[maxn];
int n, m, q;
int pre[maxn], low[maxn], clock, st[maxn], top, belong[maxn], cnt;
int fa[maxn], mark1[maxn], mark2[maxn], f[maxn][20], dep[maxn];

void dfs(int u, int from) {
	pre[u] = low[u] = ++clock;
	st[++top] = u;
	for(int j = 0; j < E[u].size(); j++) {
		int v = E[u][j];
		if(j != from) continue;
		if(!pre[v])
			dfs(v, u), low[u] = min(low[u], low[v]);
		else low[u] = min(low[u], pre[v]);
	}
	if(pre[u] == low[u]) {
		int tmp; cnt++;
		do {
			tmp = st[top--];
			belong[tmp] = cnt;
		} while(tmp != u);
	}
}

int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }

void dfs1(int u) {
	dep[u] = dep[f[u][0]] + 1;
	for(int i = 1; i < 20; i++)
		f[u][i] = f[f[u][i - 1]][i - 1];
	for(int j = 0; j < E[u].size(); j++) {
		int v = E[u][j];
		if(v == f[u][0]) continue;
		f[v][0] = u;
		dfs1(v);
	}
}

int lca(int u, int v) {
	if(dep[u] > dep[v])
		swap(u, v);
	for(int j = 19; j >= 0; j--)
		if(dep[f[v][j]] >= dep[u])
			v = f[v][j];
	if(u == v) return u;
	for(int j = 19; j >= 0; j--)
		if(f[u][j] != f[v][j]) u = f[u][j], v = f[v][j];
	return f[u][0];
}

void dfs2(int u) {
	for(int j = 0; j < E[u].size(); j++) {
		int v = E[u][j];
		if(v != f[u][0]) {
			dfs2(v);
			mark1[u] += mark1[v];
			mark2[u] += mark2[v];
		}
	}
	if(mark1[u] && mark2[u])
		exit((puts("No"),0));
}

int main() {
	scanf("%d%d%d", &n, &m, &q);
	for(int i = 1; i <= m; i++) {
		int u, v; scanf("%d%d", &u, &v);
		E[u].push_back(v);
		E[v].push_back(u);
		edge[i] = make_pair(u, v);
	}
	for(int i = 1; i <= n; i++)
		if(!belong[i]) dfs(i, 0);
	for(int i = 1; i <= n; i++)
		E[i].clear();
	for(int i = 1; i <= cnt; i++)
		fa[i] = i;
	for(int i = 1; i <= m; i++) {
		int u = belong[edge[i].first];
		int v = belong[edge[i].second];
		if(u != v) {
			E[u].push_back(v);
			E[v].push_back(u);
			fa[find(u)] = find(v);
		}
	}
	for(int i = 1; i <= cnt; i++)
		if(i == find(i))
			dfs1(i);
	for(int i = 1; i <= q; i++) {
		int u, v; scanf("%d%d", &u, &v);
		u = belong[u]; v = belong[v];
		if(find(u) != find(v)) {
			puts("No");
			return 0;
		}
		int anc = lca(u, v);
		mark1[u]++; mark2[v]++;
		mark1[anc]--; mark2[anc]--;
	}
	for(int i = 1; i <= cnt; i++)
		if(i == find(i))
			dfs2(i);
	puts("Yes");
	return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;

const int maxn = 200000 + 10;

typedef pair<int, int> ii;

vector<int> E[maxn];
ii edge[maxn];
int n, m, q;
int pre[maxn], low[maxn], clock, st[maxn], top, belong[maxn], cnt;
int fa[maxn], mark1[maxn], mark2[maxn], f[maxn][20], dep[maxn];

void dfs(int u, int f) {
	pre[u] = low[u] = ++clock;
	st[++top] = u;
	for(int j = 0; j < E[u].size(); j++) {
		int v = E[u][j];
		if(v == f) continue;
		if(!pre[v])
			dfs(v, u), low[u] = min(low[u], low[v]);
		else low[u] = min(low[u], pre[v]);
	}
	if(pre[u] == low[u]) {
		int tmp; cnt++;
		do {
			tmp = st[top--];
			belong[tmp] = cnt;
		} while(tmp != u);
	}
}

int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }

void dfs1(int u) {
	dep[u] = dep[f[u][0]] + 1;
	for(int i = 1; i < 20; i++)
		f[u][i] = f[f[u][i - 1]][i - 1];
	for(int j = 0; j < E[u].size(); j++) {
		int v = E[u][j];
		if(v == f[u][0]) continue;
		f[v][0] = u;
		dfs1(v);
	}
}

int lca(int u, int v) {
	if(dep[u] > dep[v])
		swap(u, v);
	for(int j = 19; j >= 0; j--)
		if(dep[f[v][j]] >= dep[u])
			v = f[v][j];
	if(u == v) return u;
	for(int j = 19; j >= 0; j--)
		if(f[u][j] != f[v][j]) u = f[u][j], v = f[v][j];
	return f[u][0];
}

void dfs2(int u) {
	for(int j = 0; j < E[u].size(); j++) {
		int v = E[u][j];
		if(v != f[u][0]) {
			dfs2(v);
			mark1[u] += mark1[v];
			mark2[u] += mark2[v];
		}
	}
	if(mark1[u] && mark2[u])
		exit((puts("No"),0));
}

int main() {
	scanf("%d%d%d", &n, &m, &q);
	for(int i = 1; i <= n; i++)
		fa[i] = i;
	for(int i = 1; i <= m; i++) {
		int u, v; scanf("%d%d", &u, &v);
		E[u].push_back(v);
		E[v].push_back(u);
		edge[i] = make_pair(u, v);
	}
	for(int i = 1; i <= n; i++)
		if(!belong[i]) dfs(i, -1);
	for(int i = 1; i <= n; i++)
		E[i].clear();
	for(int i = 1; i <= m; i++) {
		int u = belong[edge[i].first];
		int v = belong[edge[i].second];
		if(u != v) {
			E[u].push_back(v);
			E[v].push_back(u);
			fa[find(u)] = find(v);
		}
	}
	for(int i = 1; i <= n; i++)
		if(i == find(i))
			dfs1(i);
	for(int i = 1; i <= q; i++) {
		int u, v; scanf("%d%d", &u, &v);
		u = belong[u]; v = belong[v];
		if(find(u) != find(v)) {
			puts("No");
			return 0;
		}
		int anc = lca(u, v);
		mark1[u]++; mark2[v]++;
		mark1[anc]--; mark2[anc]--;
	}
	for(int i = 1; i <= n; i++)
		if(i == find(i))
			dfs2(i);
	puts("Yes");
	return 0;
}


#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 200200
using namespace std;

struct edge{
	int x,y;
}edges[M];
struct abcd{
	int to,next;
}table[M<<1];
int head[M],tot=1;

int n,m,q,cnt;

int belong[M],dpt[M],fa[M][18];

int mark1[M],mark2[M];

void Add(int x,int y)
{
	table[++tot].to=y;
	table[tot].next=head[x];
	head[x]=tot;
}
void Tarjan(int x,int from)
{
	static int dpt[M],low[M],T;
	static int stack[M],top;
	int i;
	dpt[x]=low[x]=++T;
	stack[++top]=x;
	for(i=head[x];i;i=table[i].next)
		if(i != from)
		{
			if(dpt[table[i].to])
				low[x]=min(low[x],dpt[table[i].to]);
			else
				Tarjan(table[i].to,i),low[x]=min(low[x],low[table[i].to]);
		}
	if(dpt[x]==low[x])
	{
		int t;++cnt;
		do{
			t=stack[top--];
			belong[t]=cnt;
		}while(t!=x);
	}
}
namespace Union_Find_Set{
	int fa[M],rank[M];
	int Find(int x)
	{
		if(!fa[x]||fa[x]==x)
			return fa[x]=x;
		return fa[x]=Find(fa[x]);
	}
	void Union(int x,int y)
	{
		x=Find(x);y=Find(y);
		if(x==y) return ;
		if(rank[x]>rank[y])
			swap(x,y);
		if(rank[x]==rank[y])
			++rank[y];
		fa[x]=y;
	}
}
void DFS1(int x)
{
	int i;
	dpt[x]=dpt[fa[x][0]]+1;
	for(i=1;i<=17;i++)
		fa[x][i]=fa[fa[x][i-1]][i-1];
	for(i=head[x];i;i=table[i].next)
		if(table[i].to!=fa[x][0])
		{
			fa[table[i].to][0]=x;
			DFS1(table[i].to);
		}
}
int LCA(int x,int y)
{
	int j;
	if(dpt[x]<dpt[y])
		swap(x,y);
	for(j=17;~j;j--)
		if(dpt[fa[x][j]]>=dpt[y])
			x=fa[x][j];
	if(x==y) return x;
	for(j=17;~j;j--)
		if(fa[x][j]!=fa[y][j])
			x=fa[x][j],y=fa[y][j];
	return fa[x][0];
}
void DFS2(int x)
{
	int i;
	for(i=head[x];i;i=table[i].next)
		if(table[i].to!=fa[x][0])
		{
			DFS2(table[i].to);
			mark1[x]+=mark1[table[i].to];
			mark2[x]+=mark2[table[i].to];
		}
	if(mark1[x]&&mark2[x])
		exit((puts("No"),0));
}
int main()
{
	using namespace Union_Find_Set;
	int i,x,y;
	cin>>n>>m>>q;
	for(i=1;i<=m;i++)
	{
		scanf("%d%d",&x,&y);
		edges[i].x=x;
		edges[i].y=y;
		Add(x,y);Add(y,x);
	}
	for(i=1;i<=n;i++)
		if(!belong[i])
			Tarjan(i,0);
	memset(head,0,sizeof head);tot=0;
	for(i=1;i<=m;i++)
	{
		x=belong[edges[i].x];
		y=belong[edges[i].y];
		if(x!=y)
			Add(x,y),Add(y,x),Union(x,y);
	}
	for(i=1;i<=cnt;i++)
		if(i==Find(i))
			DFS1(i);
	for(i=1;i<=q;i++)
	{
		scanf("%d%d",&x,&y);
		x=belong[x];
		y=belong[y];
		if(Find(x)!=Find(y))
			return puts("No"),0;
		int lca=LCA(x,y);
		mark1[x]++;mark2[y]++;
		mark1[lca]--;mark2[lca]--;
	}
	for(i=1;i<=cnt;i++)
		if(i==Find(i))
			DFS2(i);
	puts("Yes");
	return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;

const int maxn = 200000 + 10;

typedef pair<int, int> ii;

vector<int> E[maxn];
ii edge[maxn];
int n, m, q;
int pre[maxn], low[maxn], clock, st[maxn], top, belong[maxn], cnt;
int fa[maxn], mark1[maxn], mark2[maxn], f[maxn][20], dep[maxn];

void dfs(int u, int from) {
	pre[u] = low[u] = ++clock;
	st[++top] = u;
	for(int j = 0; j < E[u].size(); j++) {
		int v = E[u][j];
		if(j == from) continue;
		if(!pre[v])
			dfs(v, u), low[u] = min(low[u], low[v]);
		else low[u] = min(low[u], pre[v]);
	}
	if(pre[u] == low[u]) {
		int tmp; cnt++;
		do {
			tmp = st[top--];
			belong[tmp] = cnt;
		} while(tmp != u);
	}
}

int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }

void dfs1(int u) {
	dep[u] = dep[f[u][0]] + 1;
	for(int i = 1; i < 20; i++)
		f[u][i] = f[f[u][i - 1]][i - 1];
	for(int j = 0; j < E[u].size(); j++) {
		int v = E[u][j];
		if(v == f[u][0]) continue;
		f[v][0] = u;
		dfs1(v);
	}
}

int lca(int u, int v) {
	if(dep[u] > dep[v])
		swap(u, v);
	for(int j = 19; j >= 0; j--)
		if(dep[f[v][j]] >= dep[u])
			v = f[v][j];
	if(u == v) return u;
	for(int j = 19; j >= 0; j--)
		if(f[u][j] != f[v][j]) u = f[u][j], v = f[v][j];
	return f[u][0];
}

void dfs2(int u) {
	for(int j = 0; j < E[u].size(); j++) {
		int v = E[u][j];
		if(v != f[u][0]) {
			dfs2(v);
			mark1[u] += mark1[v];
			mark2[u] += mark2[v];
		}
	}
	if(mark1[u] && mark2[u])
		exit((puts("No"),0));
}

int main() {
	scanf("%d%d%d", &n, &m, &q);
	for(int i = 1; i <= m; i++) {
		int u, v; scanf("%d%d", &u, &v);
		E[u].push_back(v);
		E[v].push_back(u);
		edge[i] = make_pair(u, v);
	}
	for(int i = 1; i <= n; i++)
		if(!belong[i]) dfs(i, 0);
	for(int i = 1; i <= n; i++)
		E[i].clear();
	for(int i = 1; i <= cnt; i++)
		fa[i] = i;
	for(int i = 1; i <= m; i++) {
		int u = belong[edge[i].first];
		int v = belong[edge[i].second];
		if(u != v) {
			E[u].push_back(v);
			E[v].push_back(u);
			fa[find(u)] = find(v);
		}
	}
	for(int i = 1; i <= cnt; i++)
		if(i == find(i))
			dfs1(i);
	for(int i = 1; i <= q; i++) {
		int u, v; scanf("%d%d", &u, &v);
		u = belong[u]; v = belong[v];
		if(find(u) != find(v)) {
			puts("No");
			return 0;
		}
		int anc = lca(u, v);
		mark1[u]++; mark2[v]++;
		mark1[anc]--; mark2[anc]--;
	}
	for(int i = 1; i <= cnt; i++)
		if(i == find(i))
			dfs2(i);
	puts("Yes");
	return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;

const int maxn = 200000 + 10;

typedef pair<int, int> ii;

vector<int> E[maxn];
ii edge[maxn];
int n, m, q;
int pre[maxn], low[maxn], clock, st[maxn], top, belong[maxn], cnt;
int fa[maxn], mark1[maxn], mark2[maxn], f[maxn][20], dep[maxn];

void dfs(int u, int f) {
	pre[u] = low[u] = ++clock;
	st[++top] = u;
	for(int j = 0; j < E[u].size(); j++) {
		int v = E[u][j];
		if(v == f) continue;
		if(!pre[v])
			dfs(v, u), low[u] = min(low[u], low[v]);
		else low[u] = min(low[u], pre[v]);
	}
	if(pre[u] == low[u]) {
		int tmp; cnt++;
		do {
			tmp = st[top--];
			belong[tmp] = cnt;
		} while(tmp != u);
	}
}

int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }

void dfs1(int u) {
	dep[u] = dep[f[u][0]] + 1;
	for(int i = 1; i < 20; i++)
		f[u][i] = f[f[u][i - 1]][i - 1];
	for(int j = 0; j < E[u].size(); j++) {
		int v = E[u][j];
		if(v == f[u][0]) continue;
		f[v][0] = u;
		dfs1(v);
	}
}

int lca(int u, int v) {
	if(dep[u] > dep[v])
		swap(u, v);
	for(int j = 19; j >= 0; j--)
		if(dep[f[v][j]] >= dep[u])
			v = f[v][j];
	if(u == v) return u;
	for(int j = 19; j >= 0; j--)
		if(f[u][j] != f[v][j]) u = f[u][j], v = f[v][j];
	return f[u][0];
}

void dfs2(int u) {
	for(int j = 0; j < E[u].size(); j++) {
		int v = E[u][j];
		if(v != f[u][0]) {
			dfs2(v);
			mark1[u] += mark1[v];
			mark2[u] += mark2[v];
		}
	}
	if(mark1[u] && mark2[u])
		exit((puts("No"),0));
}

int main() {
	scanf("%d%d%d", &n, &m, &q);
	for(int i = 1; i <= n; i++)
		fa[i] = i;
	for(int i = 1; i <= m; i++) {
		int u, v; scanf("%d%d", &u, &v);
		E[u].push_back(v);
		E[v].push_back(u);
		edge[i] = make_pair(u, v);
	}
	for(int i = 1; i <= n; i++)
		if(!belong[i]) dfs(i, -1);
	for(int i = 1; i <= n; i++)
		E[i].clear();
	for(int i = 1; i <= m; i++) {
		int u = belong[edge[i].first];
		int v = belong[edge[i].second];
		if(u != v) {
			E[u].push_back(v);
			E[v].push_back(u);
			fa[find(u)] = find(v);
		}
	}
	for(int i = 1; i <= cnt; i++)
		if(i == find(i))
			dfs1(i);
	for(int i = 1; i <= q; i++) {
		int u, v; scanf("%d%d", &u, &v);
		u = belong[u]; v = belong[v];
		if(find(u) != find(v)) {
			puts("No");
			return 0;
		}
		int anc = lca(u, v);
		mark1[u]++; mark2[v]++;
		mark1[anc]--; mark2[anc]--;
	}
	for(int i = 1; i <= cnt; i++)
		if(i == find(i))
			dfs2(i);
	puts("Yes");
	return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;

const int maxn = 200000 + 10;

typedef pair<int, int> ii;

vector<int> E[maxn];
ii edge[maxn];
int n, m, q;
int pre[maxn], low[maxn], clock, st[maxn], top, belong[maxn], cnt;
int fa[maxn], mark1[maxn], mark2[maxn], f[maxn][20], dep[maxn];

void dfs(int u, int f) {
	pre[u] = low[u] = ++clock;
	st[++top] = u;
	for(int j = 0; j < E[u].size(); j++) {
		int v = E[u][j];
		if(v == f) continue;
		if(!pre[v])
			dfs(v, u), low[u] = min(low[u], low[v]);
		else low[u] = min(low[u], pre[v]);
	}
	if(pre[u] == low[u]) {
		int tmp; cnt++;
		do {
			tmp = st[top--];
			belong[tmp] = cnt;
		} while(tmp != u);
	}
}

int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }

void dfs1(int u) {
	dep[u] = dep[f[u][0]] + 1;
	for(int i = 1; i < 20; i++)
		f[u][i] = f[f[u][i - 1]][i - 1];
	for(int j = 0; j < E[u].size(); j++) {
		int v = E[u][j];
		if(v == f[u][0]) continue;
		f[v][0] = u;
		dfs1(v);
	}
}

int lca(int u, int v) {
	if(dep[u] > dep[v])
		swap(u, v);
	for(int j = 19; j >= 0; j--)
		if(dep[f[v][j]] >= dep[u])
			v = f[v][j];
	if(u == v) return u;
	for(int j = 19; j >= 0; j--)
		if(f[u][j] != f[v][j]) u = f[u][j], v = f[v][j];
	return f[u][0];
}

void dfs2(int u) {
	for(int j = 0; j < E[u].size(); j++) {
		int v = E[u][j];
		if(v != f[u][0]) {
			dfs2(v);
			mark1[u] += mark1[v];
			mark2[u] += mark2[v];
		}
	}
	if(mark1[u] && mark2[u])
		exit((puts("No"),0));
}

int main() {
	scanf("%d%d%d", &n, &m, &q);
	for(int i = 1; i <= n; i++)
		fa[i] = i;
	for(int i = 1; i <= m; i++) {
		int u, v; scanf("%d%d", &u, &v);
		E[u].push_back(v);
		E[v].push_back(u);
		edge[i] = make_pair(u, v);
	}
	for(int i = 1; i <= n; i++)
		if(!pre[i]) dfs(i, -1);
	for(int i = 1; i <= n; i++)
		E[i].clear();
	for(int i = 1; i <= m; i++) {
		int u = belong[edge[i].first];
		int v = belong[edge[i].second];
		if(u != v) {
			E[u].push_back(v);
			E[v].push_back(u);
			fa[find(u)] = find(v);
		}
	}
	for(int i = 1; i <= cnt; i++)
		if(i == find(i))
			dfs1(i);
	for(int i = 1; i <= q; i++) {
		int u, v; scanf("%d%d", &u, &v);
		u = belong[u]; v = belong[v];
		if(find(u) != find(v)) {
			puts("No");
			return 0;
		}
		int anc = lca(u, v);
		mark1[u]++; mark2[v]++;
		mark1[anc]--; mark2[anc]--;
	}
	for(int i = 1; i <= cnt; i++)
		if(i == find(i))
			dfs2(i);
	puts("Yes");
	return 0;
}


#include <cstdio>
#include <algorithm>
using namespace std;
#define N 200000 + 5

int n, m, q, tot = 1, Head[N], Col[N], Fa[N], An[N], _An[N], Dep[N], _Fa[2][N];

struct Edge
{
	int next, node;
	bool flag;
}h[N << 1];

inline void addedge(int u, int v)
{
	h[++ tot].next = Head[u], Head[u] = tot;
	h[tot].node = v;
}

inline void dfs(int z, int col)
{
	for (int i = Head[z]; i; i = h[i].next)
	{
		int d = h[i].node;
		if (Col[d] == col) continue ;
		Col[d] = col;
		Fa[d] = z, Dep[d] = Dep[z] + 1;
		h[i].flag = h[i ^ 1].flag = 1;
		dfs(d, col);
	}
}

inline int Find(int x)
{
	return x == An[x] ? x : An[x] = Find(An[x]);
}

inline int Find(int op, int x)
{
	return x == _Fa[op][x] ? x : _Fa[op][x] = Find(op, _Fa[op][x]);
}

inline void Union(int u, int v)
{
	if (Dep[u] < Dep[v]) swap(u, v);
	for (u = Find(u); Dep[u] > Dep[v]; u = Find(Fa[u]))
		An[u] = Find(Fa[u]);
}

inline bool Modify(int u, int v)
{
	bool op = 0;
	for (u = Find(op, u), v = Find(op, v); u != v; u = Find(op, Fa[u]), v = Find(op, v))
	{
		if (Dep[u] < Dep[v]) swap(u, v), op ^= 1;
		_Fa[op][u] = Find(op, Fa[u]);
	}
}

int main()
{
	scanf("%d%d%d", &n, &m, &q);
	for (int i = 1, u, v; i <= m; i ++)
	{
		scanf("%d%d", &u, &v);
		addedge(u, v), addedge(v, u);
	}
	for (int i = 1; i <= n; i ++)
	{
		if (Col[i]) continue ;
		Col[i] = i, Dep[i] = 1;
		dfs(i, i);
	}
	for (int i = 1; i <= n; i ++)
		An[i] = i;
	for (int i = 2; i <= tot; i += 2)
	{
		if (h[i].flag) continue ;
		Union(h[i].node, h[i ^ 1].node);
	}
	for (int i = 1; i <= n; i ++)
	{
		_An[i] = Find(i);
		_Fa[0][i] = _Fa[1][i] = Find(i);
	}
	bool ok = 1;
	for (int i = 1, u, v; ok && i <= q; i ++)
	{
		scanf("%d%d", &u, &v);
		if (Col[u] != Col[v]) ok = 0;
		u = _An[u], v = _An[v];
		Modify(u, v);
	}
	for (int i = 1; ok && i <= n; i ++)
	{
		if (i != _An[i]) continue ;
		int u = Find(0, i), v = Find(1, i);
		if (u != i && v != i) ok = 0;
	}
	puts(ok ? "Yes" : "No");
	return 0;
}


#include <cstdio>
#include <algorithm>
using namespace std;
#define N 200000 + 5

int n, m, q, tot = 1, Head[N], Col[N], Fa[N], An[N], _An[N], Dep[N], E[N][2], Dir[N];

struct Edge
{
	int next, node;
	bool flag;
}h[N << 1];

inline void addedge(int u, int v)
{
	h[++ tot].next = Head[u], Head[u] = tot;
	h[tot].node = v;
}

inline void dfs(int z, int col)
{
	for (int i = Head[z]; i; i = h[i].next)
	{
		int d = h[i].node;
		if (Col[d] == col) continue ;
		Col[d] = col;
		Fa[d] = z, Dep[d] = Dep[z] + 1;
		h[i].flag = h[i ^ 1].flag = 1;
		dfs(d, col);
	}
}

inline int Find(int x)
{
	return x == An[x] ? x : An[x] = Find(An[x]);
}

inline void Union(int u, int v)
{
	if (Dep[u] < Dep[v]) swap(u, v);
	for (u = Find(u); Dep[u] > Dep[v]; u = Find(Fa[u]))
		An[u] = Find(Fa[u]);
}

inline bool Modify(int u, int v)
{
	int op = -1;
	for (; u != v; u = Find(Fa[u]))
	{
		if (Dep[u] < Dep[v]) swap(u, v), op = -op;
		if (Dir[u] && Dir[u] != op) return 0;
		Dir[u] = op, An[u] = Find(Fa[u]);
	}
	return 1;
}

int main()
{
	scanf("%d%d%d", &n, &m, &q);
	for (int i = 1, u, v; i <= m; i ++)
	{
		scanf("%d%d", &u, &v);
		addedge(u, v), addedge(v, u);
	}
	for (int i = 1; i <= n; i ++)
	{
		if (Col[i]) continue ;
		Col[i] = i, Dep[i] = 1;
		dfs(i, i);
	}
	for (int i = 1; i <= n; i ++)
		An[i] = i;
	for (int i = 2; i <= tot; i += 2)
	{
		if (h[i].flag) continue ;
		Union(h[i].node, h[i ^ 1].node);
	}
	for (int i = 1; i <= n; i ++)
		_An[i] = Find(i);
	bool ok = 1;
	for (int i = 1, u, v; ok && i <= q; i ++)
	{
		scanf("%d%d", &u, &v);
		if (Col[u] != Col[v]) ok = 0;
		u = _An[u], v = _An[v];
		ok = Modify(u, v);
	}
	puts(ok ? "Yes" : "No");
	return 0;
}


#include <cstdio>
#include <algorithm>
using namespace std;
#define N 200000 + 5

int n, m, q, tot = 1, Head[N], Col[N], Fa[N], An[N], _An[N], Dep[N], _Fa[2][N];

struct Edge
{
	int next, node;
	bool flag;
}h[N << 1];

inline void addedge(int u, int v)
{
	h[++ tot].next = Head[u], Head[u] = tot;
	h[tot].node = v;
}

inline void dfs(int z, int col)
{
	for (int i = Head[z]; i; i = h[i].next)
	{
		int d = h[i].node;
		if (Col[d] == col) continue ;
		Col[d] = col;
		Fa[d] = z, Dep[d] = Dep[z] + 1;
		h[i].flag = h[i ^ 1].flag = 1;
		dfs(d, col);
	}
}

inline int Find(int x)
{
	return x == An[x] ? x : An[x] = Find(An[x]);
}

inline int Find(int op, int x)
{
	return x == _Fa[op][x] ? x : _Fa[op][x] = Find(op, _Fa[op][x]);
}

inline void Union(int u, int v)
{
	if (Dep[u] < Dep[v]) swap(u, v);
	for (u = Find(u); Dep[u] > Dep[v]; u = Find(Fa[u]))
		An[u] = Find(Fa[u]);
}

inline bool Modify(int u, int v)
{
	bool op = 0;
	for (u = Find(op, u), v = Find(op, v); u != v; u = Find(op, Fa[u]), v = Find(op, v))
	{
		if (Dep[u] < Dep[v])
		{
			swap(u, v), op ^= 1;
			u = Find(op, u), v = Find(op, v);
		}
		_Fa[op][u] = Find(op, Fa[u]);
	}
}

int main()
{
	scanf("%d%d%d", &n, &m, &q);
	for (int i = 1, u, v; i <= m; i ++)
	{
		scanf("%d%d", &u, &v);
		addedge(u, v), addedge(v, u);
	}
	for (int i = 1; i <= n; i ++)
	{
		if (Col[i]) continue ;
		Col[i] = i, Dep[i] = 1;
		dfs(i, i);
	}
	for (int i = 1; i <= n; i ++)
		An[i] = i;
	for (int i = 2; i <= tot; i += 2)
	{
		if (h[i].flag) continue ;
		Union(h[i].node, h[i ^ 1].node);
	}
	for (int i = 1; i <= n; i ++)
	{
		_An[i] = Find(i);
		_Fa[0][i] = _Fa[1][i] = Find(i);
	}
	bool ok = 1;
	for (int i = 1, u, v; ok && i <= q; i ++)
	{
		scanf("%d%d", &u, &v);
		if (Col[u] != Col[v]) ok = 0;
		u = _An[u], v = _An[v];
		Modify(u, v);
	}
	for (int i = 1; ok && i <= n; i ++)
	{
		if (i != _An[i]) continue ;
		int u = Find(0, i), v = Find(1, i);
		if (u != i && v != i) ok = 0;
	}
	puts(ok ? "Yes" : "No");
	return 0;
}


#include <cstdio>
#include <algorithm>
using namespace std;
#define N 200000 + 5
#define LOGN 18

int n, m, q, tot = 1, Head[N], _Head[N], Col[N], Fa[N], An[N], _An[N], Dep[N], _Fa[2][N], STL[N][LOGN], Log[N];

struct Edge
{
	int next, node;
	bool flag;
}h[N << 1], Tree[N];

inline void addedge(Edge *E, int *head, int u, int v)
{
	E[++ tot].next = head[u], head[u] = tot;
	E[tot].node = v;
}

inline void dfs(int z, int col)
{
	for (int i = Head[z]; i; i = h[i].next)
	{
		int d = h[i].node;
		if (Col[d] == col) continue ;
		Col[d] = col;
		Fa[d] = z, Dep[d] = Dep[z] + 1;
		h[i].flag = h[i ^ 1].flag = 1;
		dfs(d, col);
	}
}

inline void DFS(int z, int fa)
{
	for (int i = Head[z]; i; i = h[i].next)
	{
		if (!h[i].flag) continue ;
		int d = h[i].node;
		if (d == fa) continue ;
		if (d == _An[d])
		{
			STL[d][0] = _An[z], Dep[d] = Dep[_An[z]] + 1;
			addedge(Tree, _Head, _An[z], d);
		}
		for (int x = _An[z], j = 0; STL[x][j]; x = STL[x][j ++])
			STL[d][j + 1] = STL[x][j];
		DFS(d, z);
	}
}

inline int Find(int x)
{
	return x == An[x] ? x : An[x] = Find(An[x]);
}

inline int Find(int op, int x)
{
	return x == _Fa[op][x] ? x : _Fa[op][x] = Find(op, _Fa[op][x]);
}

inline void Union(int u, int v)
{
	if (Dep[u] < Dep[v]) swap(u, v);
	for (u = Find(u); Dep[u] > Dep[v]; u = Find(Fa[u]))
		An[u] = Find(Fa[u]);
}

inline int LCA(int u, int v)
{
	if (Dep[u] < Dep[v]) swap(u, v);
	for (int t = Dep[u] - Dep[v]; t; t -= (t & -t))
	{
		int d = Log[t & -t];
		u = STL[u][d];
	}
	if (u == v) return u;
	for (int i = LOGN - 1; STL[u][0] != STL[v][0]; i --)
		if (STL[u][i] != STL[v][i])
		{
			u = STL[u][i];
			v = STL[v][i];
		}
	return STL[u][0];
}

inline void Modify(int u, int v, int op)
{
	for (u = Find(op, u); Dep[u] > Dep[v]; u = Find(op, STL[u][0]))
		_Fa[op][u] = Find(op, STL[u][0]);
}

int main()
{
	scanf("%d%d%d", &n, &m, &q);
	for (int i = 1, u, v; i <= m; i ++)
	{
		scanf("%d%d", &u, &v);
		addedge(h, Head, u, v), addedge(h, Head, v, u);
	}
	for (int i = 1; i <= n; i ++)
	{
		if (Col[i]) continue ;
		Col[i] = i, Dep[i] = 1;
		dfs(i, i);
	}
	for (int i = 1; i <= n; i ++)
	{
		An[i] = i;
		if (i > 1) Log[i] = Log[i >> 1] + 1;
	}
	for (int i = 2; i <= tot; i += 2)
	{
		if (h[i].flag) continue ;
		Union(h[i].node, h[i ^ 1].node);
	}
	tot = 0;
	for (int i = 1; i <= n; i ++)
	{
		_An[i] = Find(i);
		_Fa[0][i] = _Fa[1][i] = i;
	}
	for (int i = 1; i <= n; i ++)
	{
		if (Col[i] != i) continue ;
		Dep[i] = 1;
		DFS(i, 0);
	}
	bool ok = 1;
	for (int i = 1, u, v; ok && i <= q; i ++)
	{
		scanf("%d%d", &u, &v);
		if (Col[u] != Col[v]) ok = 0;
		u = _An[u], v = _An[v];
		int lca = LCA(u, v);
		Modify(u, lca, 0);
		Modify(v, lca, 1);
	}
	for (int i = 1; ok && i <= n; i ++)
	{
		if (i != _An[i]) continue ;
		int u = Find(0, i), v = Find(1, i);
		if (u != i && v != i) ok = 0;
	}
	puts(ok ? "Yes" : "No");
	return 0;
}


#include <cstdio>
#include <algorithm>
using namespace std;
#define N 200000 + 5

int n, m, q, tot = 1, Head[N], Col[N], Fa[N], An[N], _An[N], Dep[N], E[N][2], Dir[N];

struct Edge
{
	int next, node;
	bool flag;
}h[N << 1];

inline void addedge(int u, int v)
{
	h[++ tot].next = Head[u], Head[u] = tot;
	h[tot].node = v;
}

inline void dfs(int z, int col)
{
	for (int i = Head[z]; i; i = h[i].next)
	{
		int d = h[i].node;
		if (Col[d] == col) continue ;
		Col[d] = col;
		Fa[d] = z, Dep[d] = Dep[z] + 1;
		h[i].flag = h[i ^ 1].flag = 1;
		dfs(d, col);
	}
}

inline int Find(int x)
{
	return x == An[x] ? x : An[x] = Find(An[x]);
}

inline void Union(int u, int v)
{
	if (Dep[u] < Dep[v]) swap(u, v);
	for (; Dep[u] > Dep[v]; u = Find(Fa[u]))
		An[u] = Find(Fa[u]);
}

inline bool Modify(int u, int v)
{
	int op = -1;
	for (; u != v; u = Find(Fa[u]))
	{
		if (Dep[u] < Dep[v]) swap(u, v), op = -op;
		if (Dir[u] && Dir[u] != op) return 0;
		Dir[u] = op, An[u] = Find(Fa[u]);
	}
	return 1;
}

int main()
{
	scanf("%d%d%d", &n, &m, &q);
	for (int i = 1, u, v; i <= m; i ++)
	{
		scanf("%d%d", &u, &v);
		addedge(u, v), addedge(v, u);
	}
	for (int i = 1; i <= n; i ++)
	{
		if (Col[i]) continue ;
		Col[i] = An[i] = i, Dep[i] = 1;
		dfs(i, i);
	}
	for (int i = 2; i <= tot; i += 2)
	{
		if (h[i].flag) continue ;
		Union(h[i].node, h[i ^ 1].node);
	}
	for (int i = 1; i <= n; i ++)
		_An[i] = Find(i);
	bool ok = 1;
	for (int i = 1, u, v; ok && i <= q; i ++)
	{
		scanf("%d%d", &u, &v);
		if (Col[u] != Col[v]) ok = 0;
		u = _An[u], v = _An[v];
		ok = Modify(u, v);
	}
	puts(ok ? "Yes" : "No");
	return 0;
}


#include <cstdio>
#include <algorithm>
using namespace std;
#define N 200000 + 5

int n, m, q, tot = 1, Head[N], Col[N], Fa[N], An[N], _An[N], Dep[N], _Fa[2][N];

struct Edge
{
	int next, node;
	bool flag;
}h[N << 1];

inline void addedge(int u, int v)
{
	h[++ tot].next = Head[u], Head[u] = tot;
	h[tot].node = v;
}

inline void dfs(int z, int col)
{
	for (int i = Head[z]; i; i = h[i].next)
	{
		int d = h[i].node;
		if (Col[d] == col) continue ;
		Col[d] = col;
		Fa[d] = z, Dep[d] = Dep[z] + 1;
		h[i].flag = h[i ^ 1].flag = 1;
		dfs(d, col);
	}
}

inline int Find(int x)
{
	return x == An[x] ? x : An[x] = Find(An[x]);
}

inline int Find(int op, int x)
{
	return x == _Fa[op][x] ? x : _Fa[op][x] = Find(op, _Fa[op][x]);
}

inline void Union(int u, int v)
{
	if (Dep[u] < Dep[v]) swap(u, v);
	for (u = Find(u); Dep[u] > Dep[v]; u = Find(Fa[u]))
		An[u] = Find(Fa[u]);
}

inline bool Modify(int u, int v)
{
	bool op = 0;
	for (; u != v; u = Find(op, Fa[u]))
	{
		if (Dep[u] < Dep[v]) swap(u, v), op ^= 1;
		_Fa[op][u] = Find(op, Fa[u]);
	}
}

int main()
{
	scanf("%d%d%d", &n, &m, &q);
	for (int i = 1, u, v; i <= m; i ++)
	{
		scanf("%d%d", &u, &v);
		addedge(u, v), addedge(v, u);
	}
	for (int i = 1; i <= n; i ++)
	{
		if (Col[i]) continue ;
		Col[i] = i, Dep[i] = 1;
		dfs(i, i);
	}
	for (int i = 1; i <= n; i ++)
		An[i] = i;
	for (int i = 2; i <= tot; i += 2)
	{
		if (h[i].flag) continue ;
		Union(h[i].node, h[i ^ 1].node);
	}
	for (int i = 1; i <= n; i ++)
	{
		_An[i] = Find(i);
		_Fa[0][i] = _Fa[1][i] = i;
	}
	bool ok = 1;
	for (int i = 1, u, v; ok && i <= q; i ++)
	{
		scanf("%d%d", &u, &v);
		if (Col[u] != Col[v]) ok = 0;
		u = _An[u], v = _An[v];
	}
	for (int i = 1; ok && i <= n; i ++)
	{
		int u = Find(0, i), v = Find(1, i);
		if (u != i && v != i) ok = 0;
	}
	puts(ok ? "Yes" : "No");
	return 0;
}


#include <cstdio>
#include <algorithm>
using namespace std;
#define N 200000 + 5

int n, m, q, tot = 1, Head[N], Col[N], Fa[N], An[N], _An[N], Dep[N], _Fa[2][N];

struct Edge
{
	int next, node;
	bool flag;
}h[N << 1];

inline void addedge(int u, int v)
{
	h[++ tot].next = Head[u], Head[u] = tot;
	h[tot].node = v;
}

inline void dfs(int z, int col)
{
	for (int i = Head[z]; i; i = h[i].next)
	{
		int d = h[i].node;
		if (Col[d] == col) continue ;
		Col[d] = col;
		Fa[d] = z, Dep[d] = Dep[z] + 1;
		h[i].flag = h[i ^ 1].flag = 1;
		dfs(d, col);
	}
}

inline int Find(int x)
{
	return x == An[x] ? x : An[x] = Find(An[x]);
}

inline int Find(int op, int x)
{
	return x == _Fa[op][x] ? x : _Fa[op][x] = Find(op, _Fa[op][x]);
}

inline void Union(int u, int v)
{
	if (Dep[u] < Dep[v]) swap(u, v);
	for (u = Find(u); Dep[u] > Dep[v]; u = Find(Fa[u]))
		An[u] = Find(Fa[u]);
}

inline bool Modify(int u, int v)
{
	bool op = 0;
	for (; u != v; u = Find(op, Fa[u]))
	{
		if (Dep[u] < Dep[v]) swap(u, v), op ^= 1;
		_Fa[op][u] = Find(op, Fa[u]);
	}
}

int main()
{
	scanf("%d%d%d", &n, &m, &q);
	for (int i = 1, u, v; i <= m; i ++)
	{
		scanf("%d%d", &u, &v);
		addedge(u, v), addedge(v, u);
	}
	for (int i = 1; i <= n; i ++)
	{
		if (Col[i]) continue ;
		Col[i] = i, Dep[i] = 1;
		dfs(i, i);
	}
	for (int i = 1; i <= n; i ++)
		An[i] = i;
	for (int i = 2; i <= tot; i += 2)
	{
		if (h[i].flag) continue ;
		Union(h[i].node, h[i ^ 1].node);
	}
	for (int i = 1; i <= n; i ++)
	{
		_An[i] = Find(i);
		_Fa[0][i] = _Fa[1][i] = Find(i);
	}
	bool ok = 1;
	for (int i = 1, u, v; ok && i <= q; i ++)
	{
		scanf("%d%d", &u, &v);
		if (Col[u] != Col[v]) ok = 0;
		u = _An[u], v = _An[v];
		Modify(u, v);
	}
	for (int i = 1; ok && i <= n; i ++)
	{
		if (i != _An[i]) continue ;
		int u = Find(0, i), v = Find(1, i);
		if (u != i && v != i) ok = 0;
	}
	puts(ok ? "Yes" : "No");
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define N 1000000007
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
ll gcd(ll a, ll b) { for (; b; a %= b, swap(a, b)); return a; }
int dx[4] = { 1, -1, 0, 0 };
int dy[4] = { 0, 0, 1, -1 };
int n, m;
int board[3][1000001];
int dp[1000001][8];

int solve(int idx, int st)
{
    if(idx == m) return 0;
    int &ret = dp[idx][st];
    if(ret != -1) return ret;
    ret = 987654321;
    for(int bs = 0; bs < (1 << n); bs++)
    {
        int cnt = 0;
        for(int i = 0; i < n; i++)
        {
            if(bs & (1 << i))
            {
                board[i][idx] = 1 - board[i][idx];
                cnt++;
            }
        }
        bool flag = true;
        for(int i = 0; i < n - 1; i++)
        {
            int one = board[i][idx - 1] + board[i][idx]
                    + board[i + 1][idx - 1] + board[i + 1][idx];
            if(one % 2 == 0) flag = false;
        }
        if(flag) ret = min(ret, solve(idx + 1, bs) + cnt);
        for(int i = 0; i < n; i++)
        {
            if(bs & (1 << i))
                board[i][idx] = 1 - board[i][idx];
        }
    }
    return ret;
}

int main(void)
{
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    cin >> n >> m;
    if(min(n, m) >= 4)
    {
        cout << "-1";
        return 0;
    }
    if(min(n, m) == 1)
    {
        cout << "0";
        return 0;
    }
    if(n < m)
    {
        for(int i = 0; i < n; i++)
        {
            string tmp; cin >> tmp;
            for(int j = 0; j < m; j++) board[i][j] = tmp[j] - '0';
        }
    }
    else
    {
        for(int i = 0; i < n; i++)
        {
            string tmp; cin >> tmp;
            for(int j = 0; j < m; j++) board[j][i] = tmp[j] - '0';
        }
        swap(n, m);
    }
    int ans = 987654321;
    memset(dp, -1, sizeof dp);
    for(int bs = 0; bs < (1 << n); bs++)
    {
        int cnt = 0;
        for(int i = 0; i < n; i++)
        {
            if(bs & (1 << i))
            {
                board[i][0] = 1 - board[i][0];
                cnt++;
            }
        }
        int ret = solve(1, bs) + cnt;
        ans = min(ans, ret);
        for(int i = 0; i < n; i++)
        {
            if(bs & (1 << i))
                board[i][0] = 1 - board[i][0];
        }
    }
    cout << ans;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
ll gcd(ll a, ll b) { for (; b; a %= b, swap(a, b)); return a; }
int dx[4] = { 1, -1, 0, 0 };
int dy[4] = { 0, 0, 1, -1 };
#define INF 987654321
ll n, m;
ll field[10][1000002];
ll dp[10][1000002];

ll solve(ll st, ll idx)
{
    if(idx >= m) return 0;
    ll &ret = dp[st][idx];
    if(ret != -1) return ret;
    ret = INF;
    for(ll bs = 0; bs < (1 << n); bs++)
    {
        ll cnt = 0;
        for(ll i = 0; i < n; i++)
        {
            if(bs & (1 << i))
            {
                field[i][idx] = 1 - field[i][idx];
                cnt++;
            }
        }
        bool flag = true;
        for(ll i = 0; i < n - 1; i++)
        {
            ll sum = field[i][idx] + field[i][idx - 1]
                        + field[i + 1][idx] + field[i + 1][idx - 1];
            if(sum % 2 == 0) flag = false;
        }
        if(flag) ret = min(ret, solve(bs, idx + 1) + cnt);
        for(ll i = 0; i < n; i++)
        {
            if(bs & (1 << i))
                field[i][idx] = 1 - field[i][idx];
        }
    }
    return ret;
}

int main(void)
{
    memset(dp, -1, sizeof dp);
    cin >> n >> m;
    if(min(n, m) == 1)
    {
        cout << "0";
        return 0;
    }
    if(min(n, m) >= 4)
    {
        cout << "-1";
        return 0;
    }
    if(n < m)
    {
        for(ll i = 0; i < n; i++)
        {
            string st;
            for(ll j = 0; j < m; j++) field[i][j] = st[j] - '0';
        }
    }
    else
    {
        for(ll i = 0; i < n; i++)
        {
            string st;
            for(ll j = 0; j < m; j++) field[j][i] = st[j] - '0';
        }
        swap(n, m);
    }
    ll ans = INF;
    for(ll bs = 0; bs < (1 << n); bs++)
    {
        ll cnt = 0;
        for(ll i = 0; i < n; i++)
        {
            if(bs & (1 << i))
            {
                field[i][0] = 1 - field[i][0];
                cnt++;
            }
        }
        ans = min(ans, solve(bs, 1) + cnt);
        for(ll i = 0; i < n; i++)
        {
            if(bs & (1 << i))
                field[i][0] = 1 - field[i][0];
        }
    }
    cout << ans;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
ll gcd(ll a, ll b) { for (; b; a %= b, swap(a, b)); return a; }
int dx[4] = { 1, -1, 0, 0 };
int dy[4] = { 0, 0, 1, -1 };
#define INF 987654321
ll n, m;
ll field[3][1000002];
ll dp[10][1000002];

ll solve(ll st, ll idx)
{
    if(idx >= m) return 0;
    ll &ret = dp[st][idx];
    if(ret != -1) return ret;
    ret = INF;
    for(ll bs = 0; bs < (1 << n); bs++)
    {
        ll cnt = 0;
        for(ll i = 0; i < n; i++)
        {
            if(bs & (1 << i))
            {
                field[i][idx] = 1 - field[i][idx];
                cnt++;
            }
        }
        bool flag = true;
        for(ll i = 0; i < n - 1; i++)
        {
            ll sum = field[i][idx] + field[i][idx - 1]
                        + field[i + 1][idx] + field[i + 1][idx - 1];
            if(sum % 2 == 0) flag = false;
        }
        if(flag) ret = min(ret, solve(bs, idx + 1) + cnt);
        for(ll i = 0; i < n; i++)
        {
            if(bs & (1 << i))
                field[i][idx] = 1 - field[i][idx];
        }
    }
    return ret;
}

int main(void)
{
    cin >> n >> m;
    if(min(n, m) == 1)
    {
        cout << "0";
        return 0;
    }
    if(min(n, m) >= 4)
    {
        cout << "-1";
        return 0;
    }
    memset(dp, -1, sizeof dp);
    if(n < m)
    {
        for(ll i = 0; i < n; i++)
        {
            string st; cin >> st;
            for(ll j = 0; j < m; j++) field[i][j] = st[j] - '0';
        }
    }
    else
    {
        for(ll i = 0; i < n; i++)
        {
            string st; cin >> st;
            for(ll j = 0; j < m; j++) field[j][i] = st[j] - '0';
        }
        swap(n, m);
    }
    ll ans = INF;
    for(ll bs = 0; bs < ((ll)1 << n); bs++)
    {
        ll cnt = 0;
        for(ll i = 0; i < n; i++)
        {
            if(bs & ((ll)1 << i))
            {
                field[i][0] = 1 - field[i][0];
                cnt++;
            }
        }
        ans = min(ans, solve(bs, 1) + cnt);
        for(ll i = 0; i < n; i++)
        {
            if(bs & ((ll)1 << i))
                field[i][0] = 1 - field[i][0];
        }
    }
    cout << ans;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<ll,ll> P;
typedef pair<int,int> Pi;
#define rep(i,n) for(ll i=0;i<n;i++)
#define FOR(i,a,b) for(ll i=a;i<b;i++)
#define fi first
#define se second
#define endl "\n"

template<typename T> inline bool chmax(T &a, T b){if(a<b){a=b;return true;}return false;}
template<typename T> inline bool chmin(T &a, T b){if(a>b){a=b;return true;}return false;}
template<typename T> ostream& operator<<(ostream& s,const complex<T>& d) {return s<<"("<<d.real()<<", "<<d.imag()<< ")";}
template<typename T1, typename T2> ostream& operator<<(ostream& s,const pair<T1,T2>& d) {return s<<"("<<d.first<<", "<<d.second<<")";}
template<typename T> ostream& operator<<(ostream& s, const vector<T>& d){int len=d.size();rep(i,len){s<<d[i];if(i<len-1) s<<" ";}return s;}
template<typename T> ostream& operator<<(ostream& s,const vector<vector<T>>& d){int len=d.size();rep(i,len){s<<d[i]<<endl;}return s;}
template<typename T> ostream& operator<<(ostream& s,const set<T>& v){s<<"{ ";for(auto itr=v.begin();itr!=v.end();++itr) {if (itr!=v.begin()) {s<< ", ";}s<<(*itr);}s<<" }";return s;}
template<typename T> ostream& operator<<(ostream& s,const multiset<T>& v){s<<"{ ";for(auto itr=v.begin();itr!=v.end();++itr) {if (itr!=v.begin()) {s<< ", ";}s<<(*itr);}s<<" }";return s;}
template<typename T1, typename T2> ostream& operator<<(ostream& s,const map<T1,T2>& m){s<<"{"<<endl;for(auto itr=m.begin();itr!=m.end();++itr){s<<" "<<(*itr).first<<" : "<<(*itr).second<<endl;}s<<"}"<<endl;return s;}

const ll mod=1'000'000'007;
const ll inf=1'000'000'000'000'000'00;
const int INF=1'000'000'000;
const double EPS=1e-10;
const double PI=acos(-1);

int main(){
	cin.tie(0);ios::sync_with_stdio(false);
	ll n,m;
	cin>>n>>m;
	vector<vector<int>> g(n,vector<int>(m));
	rep(i,n){
		string s;
		cin>>s;
		rep(j,m){
			g[i][j]=int(s[j]-'0');
		}
	}
	if(n>=4 && m>=4){
		cout<<-1<<endl;
		return 0;
	}
	//2*2だけ考えればok
	if(m<=n){
		vector<vector<int>> ng(m,vector<int>(n));
		rep(i,m)rep(j,n){
			ng[i][j]=g[j][i];
		}
		swap(g,ng);
		swap(n,m);
	}
	ll ans=inf;
	if(n==1){
		cout<<0<<endl;
	}else if(n==2){
		rep(S,1<<4){
			ll now=0;
			vector<vector<int>> ng(g);
			rep(i,4){
				if(S & 1<<i){
					ng[(i & 2)][(i & 1)]=!ng[(i & 2)][(i & 1)];
					now++;
				}
			}
			int cnt=ng[0][0]+ng[0][0+1]+ng[1][0]+ng[1][0+1];
			if(cnt%2==0) continue;
			FOR(j,1,m-1){
				int cnt=ng[0][j]+ng[0][j+1]+ng[1][j]+ng[1][j+1];
				if(cnt%2) continue;
				now++;
				ng[0][j+1]=!ng[0][j+1];
			}
			chmin(ans,now);
		}
	}else if(n==3){
		rep(S,1<<6){
			ll now=0;
			vector<vector<int>> ng(g);
			rep(i,6){
				if(S & 1<<i){
					if(i==0){
						ng[0][0]=!ng[0][0];
						now++;
					}
					if(i==1){
						ng[0][1]=!ng[0][1];
						now++;
					}
					if(i==2){
						ng[1][0]=!ng[1][0];
						now++;
					}
					if(i==3){
						ng[1][1]=!ng[1][1];
						now++;
					}
					if(i==4){
						ng[2][0]=!ng[2][0];
						now++;
					}
					if(i==5){
						ng[2][1]=!ng[2][1];
						now++;
					}
				}
			}
			int cnt1=ng[0][0]+ng[0][0+1]+ng[1][0]+ng[1][0+1];
			int cnt2=ng[2][0]+ng[2][0+1]+ng[1][0]+ng[1][0+1];
			if(cnt1%2==0 || cnt2%2==0) continue;
			FOR(j,1,m-1){
				int cnt1=ng[0][j]+ng[0][j+1]+ng[1][j]+ng[1][j+1];
				int cnt2=ng[2][j]+ng[2][j+1]+ng[1][j]+ng[1][j+1];
				if(cnt1%2 && cnt2%2) continue;
				if(cnt1%2==0){
					if(cnt2%2==0){
						ng[1][j+1]=!ng[1][j+1];
						now++;
					}else{
						ng[0][j+1]=!ng[0][j+1];
						now++;
					}
				}else{
					ng[2][j+1]=!ng[2][j+1];
					now++;
				}
			}
			chmin(ans,now);
		}
	}
	cout<<ans<<endl;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<ll,ll> P;
typedef pair<int,int> Pi;
#define rep(i,n) for(ll i=0;i<n;i++)
#define FOR(i,a,b) for(ll i=a;i<b;i++)
#define fi first
#define se second
#define endl "\n"

template<typename T> inline bool chmax(T &a, T b){if(a<b){a=b;return true;}return false;}
template<typename T> inline bool chmin(T &a, T b){if(a>b){a=b;return true;}return false;}
template<typename T> ostream& operator<<(ostream& s,const complex<T>& d) {return s<<"("<<d.real()<<", "<<d.imag()<< ")";}
template<typename T1, typename T2> ostream& operator<<(ostream& s,const pair<T1,T2>& d) {return s<<"("<<d.first<<", "<<d.second<<")";}
template<typename T> ostream& operator<<(ostream& s, const vector<T>& d){int len=d.size();rep(i,len){s<<d[i];if(i<len-1) s<<" ";}return s;}
template<typename T> ostream& operator<<(ostream& s,const vector<vector<T>>& d){int len=d.size();rep(i,len){s<<d[i]<<endl;}return s;}
template<typename T> ostream& operator<<(ostream& s,const set<T>& v){s<<"{ ";for(auto itr=v.begin();itr!=v.end();++itr) {if (itr!=v.begin()) {s<< ", ";}s<<(*itr);}s<<" }";return s;}
template<typename T> ostream& operator<<(ostream& s,const multiset<T>& v){s<<"{ ";for(auto itr=v.begin();itr!=v.end();++itr) {if (itr!=v.begin()) {s<< ", ";}s<<(*itr);}s<<" }";return s;}
template<typename T1, typename T2> ostream& operator<<(ostream& s,const map<T1,T2>& m){s<<"{"<<endl;for(auto itr=m.begin();itr!=m.end();++itr){s<<" "<<(*itr).first<<" : "<<(*itr).second<<endl;}s<<"}"<<endl;return s;}

const ll mod=1'000'000'007;
const ll inf=1'000'000'000'000'000'00;
const int INF=1'000'000'000;
const double EPS=1e-10;
const double PI=acos(-1);

int main(){
	cin.tie(0);ios::sync_with_stdio(false);
	ll n,m;
	cin>>n>>m;
	vector<vector<int>> g(n,vector<int>(m));
	rep(i,n){
		string s;
		cin>>s;
		rep(j,m){
			g[i][j]=int(s[j]-'0');
		}
	}
	assert((n==3 && m==3) || (n>=4 && m>=4));
	if(n>=4 && m>=4){
		cout<<-1<<endl;
		return 0;
	}
	//2*2だけ考えればok
	ll ans=0;
	if(m<=n){
		vector<vector<int>> ng(m,vector<int>(n));
		rep(i,m)rep(j,n){
			ng[i][j]=g[j][i];
		}
		swap(g,ng);
		swap(n,m);
	}
	if(n==1){
		cout<<0<<endl;
	}else if(n==2){
		rep(j,m-1){
			int cnt=g[0][j]+g[0][j+1]+g[1][j]+g[1][j+1];
			if(cnt%2) continue;
			ans++;
			if(j==0 && j!=m-2){
				int ne=g[0][j+2]+g[0][j+1]+g[1][j+2]+g[1][j+1];
				if(ne%2==0) g[0][j+1]=!g[0][j+1];
				else g[0][j]=!g[0][j];
			}else{
				g[0][j+1]=!g[0][j+1];
			}
		}
	}else if(n==3){
		rep(j,m-1){
			int cnt1=g[0][j]+g[0][j+1]+g[1][j]+g[1][j+1];
			int cnt2=g[2][j]+g[2][j+1]+g[1][j]+g[1][j+1];
			if(cnt1%2 && cnt2%2) continue;
			if(j==0 && j!=m-2){
				int ne1=g[0][j+2]+g[0][j+1]+g[1][j+2]+g[1][j+1];
				int ne2=g[2][j+2]+g[2][j+1]+g[1][j+2]+g[1][j+1];
				if(cnt1%2==0){
					if(cnt2%2==0){
						if(ne1%2 && ne2%2){
							g[1][j]=!g[1][j];
						}else{
							g[1][j+1]=!g[1][j+1];
						}
						ans++;
					}else{
						if(ne1%2==0) g[0][j+1]=!g[0][j+1];
						else g[0][j]=!g[0][j];
						ans++;
					}
				}else{
					if(ne2%2==0) g[2][j+1]=!g[2][j+1];
					else g[2][j]=!g[2][j];
					ans++;
				}
			}else{
				if(cnt1%2==0){
					if(cnt2%2==0){
						g[1][j+1]=!g[1][j+1];
						ans++;
					}else{
						g[0][j+1]=!g[0][j+1];
						ans++;
					}
				}else{
					g[2][j+1]=!g[2][j+1];
					ans++;
				}
			}
		}
	}
	cout<<ans<<endl;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<ll,ll> P;
typedef pair<int,int> Pi;
#define rep(i,n) for(ll i=0;i<n;i++)
#define FOR(i,a,b) for(ll i=a;i<b;i++)
#define fi first
#define se second
#define endl "\n"

template<typename T> inline bool chmax(T &a, T b){if(a<b){a=b;return true;}return false;}
template<typename T> inline bool chmin(T &a, T b){if(a>b){a=b;return true;}return false;}
template<typename T> ostream& operator<<(ostream& s,const complex<T>& d) {return s<<"("<<d.real()<<", "<<d.imag()<< ")";}
template<typename T1, typename T2> ostream& operator<<(ostream& s,const pair<T1,T2>& d) {return s<<"("<<d.first<<", "<<d.second<<")";}
template<typename T> ostream& operator<<(ostream& s, const vector<T>& d){int len=d.size();rep(i,len){s<<d[i];if(i<len-1) s<<" ";}return s;}
template<typename T> ostream& operator<<(ostream& s,const vector<vector<T>>& d){int len=d.size();rep(i,len){s<<d[i]<<endl;}return s;}
template<typename T> ostream& operator<<(ostream& s,const set<T>& v){s<<"{ ";for(auto itr=v.begin();itr!=v.end();++itr) {if (itr!=v.begin()) {s<< ", ";}s<<(*itr);}s<<" }";return s;}
template<typename T> ostream& operator<<(ostream& s,const multiset<T>& v){s<<"{ ";for(auto itr=v.begin();itr!=v.end();++itr) {if (itr!=v.begin()) {s<< ", ";}s<<(*itr);}s<<" }";return s;}
template<typename T1, typename T2> ostream& operator<<(ostream& s,const map<T1,T2>& m){s<<"{"<<endl;for(auto itr=m.begin();itr!=m.end();++itr){s<<" "<<(*itr).first<<" : "<<(*itr).second<<endl;}s<<"}"<<endl;return s;}

const ll mod=1'000'000'007;
const ll inf=1'000'000'000'000'000'00;
const int INF=1'000'000'000;
const double EPS=1e-10;
const double PI=acos(-1);

int main(){
	cin.tie(0);ios::sync_with_stdio(false);
	ll n,m;
	cin>>n>>m;
	vector<vector<int>> g(n,vector<int>(m));
	rep(i,n){
		string s;
		cin>>s;
		rep(j,m){
			g[i][j]=int(s[j]-'0');
		}
	}
	if(n>=4 && m>=4){
		cout<<-1<<endl;
		return 0;
	}
	//2*2だけ考えればok
	if(m<=n){
		vector<vector<int>> ng(m,vector<int>(n));
		rep(i,m)rep(j,n){
			ng[i][j]=g[j][i];
		}
		swap(g,ng);
		swap(n,m);
	}
	ll ans=inf;
	if(n==1){
		ans=0;
	}else if(n==2){
		rep(S,1<<4){
			ll now=0;
			vector<vector<int>> tmp(g);
			rep(i,4){
				if(S & 1<<i){
					ll x=i/2,y=i-x*2;
					g[x][y]=!g[x][y];
					now++;
				}
			}
			int cnt=g[0][0]+g[0][0+1]+g[1][0]+g[1][0+1];
			if(cnt%2==0){
				swap(tmp,g);
				continue;
			}
			FOR(j,1,m-1){
				int cnt=g[0][j]+g[0][j+1]+g[1][j]+g[1][j+1];
				if(cnt%2) continue;
				now++;
				g[0][j+1]=!g[0][j+1];
			}
			chmin(ans,now);
			swap(tmp,g);
		}
	}else if(n==3){
		rep(S,1<<6){
			ll now=0;
			vector<vector<int>> tmp(g);
			rep(i,6){
				if(S & 1<<i){
					ll x=i/2,y=i-x*2;
					g[x][y]=!g[x][y];
					now++;
				}
			}
			int cnt1=g[0][0]+g[0][0+1]+g[1][0]+g[1][0+1];
			int cnt2=g[2][0]+g[2][0+1]+g[1][0]+g[1][0+1];
			if(cnt1%2==0 || cnt2%2==0){
				swap(tmp,g);
				continue;
			}
			FOR(j,1,m-1){
				int cnt1=g[0][j]+g[0][j+1]+g[1][j]+g[1][j+1];
				int cnt2=g[2][j]+g[2][j+1]+g[1][j]+g[1][j+1];
				if(cnt1%2 && cnt2%2) continue;
				if(cnt1%2==0){
					if(cnt2%2==0){
						g[1][j+1]=!g[1][j+1];
						now++;
					}else{
						g[0][j+1]=!g[0][j+1];
						now++;
					}
				}else{
					g[2][j+1]=!g[2][j+1];
					now++;
				}
			}
			chmin(ans,now);
			swap(tmp,g);
		}
	}
	cout<<ans<<endl;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<ll,ll> P;
typedef pair<int,int> Pi;
#define rep(i,n) for(ll i=0;i<n;i++)
#define FOR(i,a,b) for(ll i=a;i<b;i++)
#define fi first
#define se second
#define endl "\n"

template<typename T> inline bool chmax(T &a, T b){if(a<b){a=b;return true;}return false;}
template<typename T> inline bool chmin(T &a, T b){if(a>b){a=b;return true;}return false;}
template<typename T> ostream& operator<<(ostream& s,const complex<T>& d) {return s<<"("<<d.real()<<", "<<d.imag()<< ")";}
template<typename T1, typename T2> ostream& operator<<(ostream& s,const pair<T1,T2>& d) {return s<<"("<<d.first<<", "<<d.second<<")";}
template<typename T> ostream& operator<<(ostream& s, const vector<T>& d){int len=d.size();rep(i,len){s<<d[i];if(i<len-1) s<<" ";}return s;}
template<typename T> ostream& operator<<(ostream& s,const vector<vector<T>>& d){int len=d.size();rep(i,len){s<<d[i]<<endl;}return s;}
template<typename T> ostream& operator<<(ostream& s,const set<T>& v){s<<"{ ";for(auto itr=v.begin();itr!=v.end();++itr) {if (itr!=v.begin()) {s<< ", ";}s<<(*itr);}s<<" }";return s;}
template<typename T> ostream& operator<<(ostream& s,const multiset<T>& v){s<<"{ ";for(auto itr=v.begin();itr!=v.end();++itr) {if (itr!=v.begin()) {s<< ", ";}s<<(*itr);}s<<" }";return s;}
template<typename T1, typename T2> ostream& operator<<(ostream& s,const map<T1,T2>& m){s<<"{"<<endl;for(auto itr=m.begin();itr!=m.end();++itr){s<<" "<<(*itr).first<<" : "<<(*itr).second<<endl;}s<<"}"<<endl;return s;}

const ll mod=1'000'000'007;
const ll inf=1'000'000'000'000'000'00;
const int INF=1'000'000'000;
const double EPS=1e-10;
const double PI=acos(-1);

int main(){
	cin.tie(0);ios::sync_with_stdio(false);
	ll n,m;
	cin>>n>>m;
	vector<vector<int>> g(n,vector<int>(m));
	rep(i,n){
		string s;
		cin>>s;
		rep(j,m){
			g[i][j]=int(s[j]-'0');
		}
	}
	if(n>=4 && m>=4){
		cout<<-1<<endl;
		return 0;
	}
	//2*2だけ考えればok
	ll ans=0;
	if(m<=n){
		vector<vector<int>> ng(m,vector<int>(n));
		rep(i,m)rep(j,n){
			ng[i][j]=g[j][i];
		}
		swap(g,ng);
		swap(n,m);
	}
	assert(n==3);
	if(n==1){
		cout<<0<<endl;
	}else if(n==2){
		rep(j,m-1){
			int cnt=g[0][j]+g[0][j+1]+g[1][j]+g[1][j+1];
			if(cnt%2) continue;
			ans++;
			if(j==0 && j!=m-2){
				int ne=g[0][j+2]+g[0][j+1]+g[1][j+2]+g[1][j+1];
				if(ne%2==0) g[0][j+1]=!g[0][j+1];
				else g[0][j]=!g[0][j];
			}else{
				g[0][j+1]=!g[0][j+1];
			}
		}
	}else if(n==3){
		rep(j,m-1){
			int cnt1=g[0][j]+g[0][j+1]+g[1][j]+g[1][j+1];
			int cnt2=g[2][j]+g[2][j+1]+g[1][j]+g[1][j+1];
			if(cnt1%2 && cnt2%2) continue;
			if(j==0 && j!=m-2){
				int ne1=g[0][j+2]+g[0][j+1]+g[1][j+2]+g[1][j+1];
				int ne2=g[2][j+2]+g[2][j+1]+g[1][j+2]+g[1][j+1];
				if(cnt1%2==0){
					if(cnt2%2==0){
						if(ne1%2 && ne2%2){
							g[1][j]=!g[1][j];
						}else{
							g[1][j+1]=!g[1][j+1];
						}
						ans++;
					}else{
						if(ne1%2==0) g[0][j+1]=!g[0][j+1];
						else g[0][j]=!g[0][j];
						ans++;
					}
				}else{
					if(ne2%2==0) g[2][j+1]=!g[2][j+1];
					else g[2][j]=!g[2][j];
					ans++;
				}
			}else{
				if(cnt1%2==0){
					if(cnt2%2==0){
						g[1][j+1]=!g[1][j+1];
						ans++;
					}else{
						g[0][j+1]=!g[0][j+1];
						ans++;
					}
				}else{
					g[2][j+1]=!g[2][j+1];
					ans++;
				}
			}
		}
	}
	cout<<ans<<endl;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<ll,ll> P;
typedef pair<int,int> Pi;
#define rep(i,n) for(ll i=0;i<n;i++)
#define FOR(i,a,b) for(ll i=a;i<b;i++)
#define fi first
#define se second
#define endl "\n"

template<typename T> inline bool chmax(T &a, T b){if(a<b){a=b;return true;}return false;}
template<typename T> inline bool chmin(T &a, T b){if(a>b){a=b;return true;}return false;}
template<typename T> ostream& operator<<(ostream& s,const complex<T>& d) {return s<<"("<<d.real()<<", "<<d.imag()<< ")";}
template<typename T1, typename T2> ostream& operator<<(ostream& s,const pair<T1,T2>& d) {return s<<"("<<d.first<<", "<<d.second<<")";}
template<typename T> ostream& operator<<(ostream& s, const vector<T>& d){int len=d.size();rep(i,len){s<<d[i];if(i<len-1) s<<" ";}return s;}
template<typename T> ostream& operator<<(ostream& s,const vector<vector<T>>& d){int len=d.size();rep(i,len){s<<d[i]<<endl;}return s;}
template<typename T> ostream& operator<<(ostream& s,const set<T>& v){s<<"{ ";for(auto itr=v.begin();itr!=v.end();++itr) {if (itr!=v.begin()) {s<< ", ";}s<<(*itr);}s<<" }";return s;}
template<typename T> ostream& operator<<(ostream& s,const multiset<T>& v){s<<"{ ";for(auto itr=v.begin();itr!=v.end();++itr) {if (itr!=v.begin()) {s<< ", ";}s<<(*itr);}s<<" }";return s;}
template<typename T1, typename T2> ostream& operator<<(ostream& s,const map<T1,T2>& m){s<<"{"<<endl;for(auto itr=m.begin();itr!=m.end();++itr){s<<" "<<(*itr).first<<" : "<<(*itr).second<<endl;}s<<"}"<<endl;return s;}

const ll mod=1'000'000'007;
const ll inf=1'000'000'000'000'000'00;
const int INF=1'000'000'000;
const double EPS=1e-10;
const double PI=acos(-1);

int main(){
	cin.tie(0);ios::sync_with_stdio(false);
	ll n,m;
	cin>>n>>m;
	vector<vector<int>> g(n,vector<int>(m));
	rep(i,n){
		string s;
		cin>>s;
		rep(j,m){
			g[i][j]=int(s[j]-'0');
		}
	}
	if(n>=4 && m>=4){
		cout<<-1<<endl;
		return 0;
	}
	//2*2だけ考えればok
	ll ans=0;
	if(m<=n){
		vector<vector<int>> ng(m,vector<int>(n));
		rep(i,m)rep(j,n){
			ng[i][j]=g[j][i];
		}
		swap(g,ng);
		swap(n,m);
	}
	if(n==1){
		cout<<0<<endl;
	}else if(n==2){
		rep(j,m-1){
			int cnt=g[0][j]+g[0][j+1]+g[1][j]+g[1][j+1];
			if(cnt%2) continue;
			ans++;
			if(j==0 && j!=m-2){
				int ne=g[0][j+2]+g[0][j+1]+g[1][j+2]+g[1][j+1];
				if(ne%2==0) g[0][j+1]=!g[0][j+1];
				else g[0][j]=!g[0][j];
			}else{
				g[0][j+1]=!g[0][j+1];
			}
		}
	}else if(n==3){
        rep(j,m-1){
			int cnt=g[0][j]+g[0][j+1]+g[1][j]+g[1][j+1];
			if(cnt%2) continue;
			ans++;
			if(j==0 && j!=m-2){
				int ne=g[0][j+2]+g[0][j+1]+g[1][j+2]+g[1][j+1];
				if(ne%2==0) g[0][j+1]=!g[0][j+1];
				else g[0][j]=!g[0][j];
			}else{
				g[0][j+1]=!g[0][j+1];
			}
		}
        rep(j,m-1){
			int cnt=g[2][j]+g[2][j+1]+g[1][j]+g[1][j+1];
			if(cnt%2) continue;
			ans++;
			if(j==0 && j!=m-2){
				int ne=g[2][j+2]+g[2][j+1]+g[1][j+2]+g[1][j+1];
				if(ne%2==0) g[2][j+1]=!g[2][j+1];
				else g[2][j]=!g[2][j];
			}else{
				g[2][j+1]=!g[2][j+1];
			}
		}
	}
	cout<<ans<<endl;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<ll,ll> P;
typedef pair<int,int> Pi;
#define rep(i,n) for(ll i=0;i<n;i++)
#define FOR(i,a,b) for(ll i=a;i<b;i++)
#define fi first
#define se second
#define endl "\n"

template<typename T> inline bool chmax(T &a, T b){if(a<b){a=b;return true;}return false;}
template<typename T> inline bool chmin(T &a, T b){if(a>b){a=b;return true;}return false;}
template<typename T> ostream& operator<<(ostream& s,const complex<T>& d) {return s<<"("<<d.real()<<", "<<d.imag()<< ")";}
template<typename T1, typename T2> ostream& operator<<(ostream& s,const pair<T1,T2>& d) {return s<<"("<<d.first<<", "<<d.second<<")";}
template<typename T> ostream& operator<<(ostream& s, const vector<T>& d){int len=d.size();rep(i,len){s<<d[i];if(i<len-1) s<<" ";}return s;}
template<typename T> ostream& operator<<(ostream& s,const vector<vector<T>>& d){int len=d.size();rep(i,len){s<<d[i]<<endl;}return s;}
template<typename T> ostream& operator<<(ostream& s,const set<T>& v){s<<"{ ";for(auto itr=v.begin();itr!=v.end();++itr) {if (itr!=v.begin()) {s<< ", ";}s<<(*itr);}s<<" }";return s;}
template<typename T> ostream& operator<<(ostream& s,const multiset<T>& v){s<<"{ ";for(auto itr=v.begin();itr!=v.end();++itr) {if (itr!=v.begin()) {s<< ", ";}s<<(*itr);}s<<" }";return s;}
template<typename T1, typename T2> ostream& operator<<(ostream& s,const map<T1,T2>& m){s<<"{"<<endl;for(auto itr=m.begin();itr!=m.end();++itr){s<<" "<<(*itr).first<<" : "<<(*itr).second<<endl;}s<<"}"<<endl;return s;}

const ll mod=1'000'000'007;
const ll inf=1'000'000'000'000'000'00;
const int INF=1'000'000'000;
const double EPS=1e-10;
const double PI=acos(-1);

int main(){
	cin.tie(0);ios::sync_with_stdio(false);
	ll n,m;
	cin>>n>>m;
	vector<vector<int>> g(n,vector<int>(m));
	rep(i,n){
		string s;
		cin>>s;
		rep(j,m){
			g[i][j]=int(s[j]-'0');
		}
	}
	if(n>=4 && m>=4){
		cout<<-1<<endl;
		return 0;
	}
	//2*2だけ考えればok
	if(m<=n){
		vector<vector<int>> ng(m,vector<int>(n));
		rep(i,m)rep(j,n){
			ng[i][j]=g[j][i];
		}
		swap(g,ng);
		swap(n,m);
	}
	ll ans=inf;
	if(n==1){
		cout<<0<<endl;
	}else if(n==2){
		rep(S,1<<4){
			ll now=0;
			vector<vector<int>> ng(g);
			rep(i,4){
				if(S & 1<<i){
					if(i==0) ng[0][0]=!ng[0][0];
					if(i==1) ng[0][1]=!ng[0][1];
					if(i==2) ng[1][0]=!ng[1][0];
					if(i==3) ng[1][1]=!ng[1][1];
					now++;
				}
			}
			int cnt=ng[0][0]+ng[0][0+1]+ng[1][0]+ng[1][0+1];
			if(cnt%2==0) continue;
			FOR(j,1,m-1){
				int cnt=ng[0][j]+ng[0][j+1]+ng[1][j]+ng[1][j+1];
				if(cnt%2) continue;
				now++;
				ng[0][j+1]=!ng[0][j+1];
			}
			chmin(ans,now);
		}
	}else if(n==3){
		rep(S,1<<6){
			ll now=0;
			vector<vector<int>> ng(g);
			rep(i,6){
				if(S & 1<<i){
					if(i==0){
						ng[0][0]=!ng[0][0];
						now++;
					}
					if(i==1){
						ng[0][1]=!ng[0][1];
						now++;
					}
					if(i==2){
						ng[1][0]=!ng[1][0];
						now++;
					}
					if(i==3){
						ng[1][1]=!ng[1][1];
						now++;
					}
					if(i==4){
						ng[2][0]=!ng[2][0];
						now++;
					}
					if(i==5){
						ng[2][1]=!ng[2][1];
						now++;
					}
				}
			}
			int cnt1=ng[0][0]+ng[0][0+1]+ng[1][0]+ng[1][0+1];
			int cnt2=ng[2][0]+ng[2][0+1]+ng[1][0]+ng[1][0+1];
			if(cnt1%2==0 || cnt2%2==0) continue;
			FOR(j,1,m-1){
				int cnt1=ng[0][j]+ng[0][j+1]+ng[1][j]+ng[1][j+1];
				int cnt2=ng[2][j]+ng[2][j+1]+ng[1][j]+ng[1][j+1];
				if(cnt1%2 && cnt2%2) continue;
				if(cnt1%2==0){
					if(cnt2%2==0){
						ng[1][j+1]=!ng[1][j+1];
						now++;
					}else{
						ng[0][j+1]=!ng[0][j+1];
						now++;
					}
				}else{
					ng[2][j+1]=!ng[2][j+1];
					now++;
				}
			}
			chmin(ans,now);
		}
	}
	cout<<ans<<endl;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<ll,ll> P;
typedef pair<int,int> Pi;
#define rep(i,n) for(ll i=0;i<n;i++)
#define FOR(i,a,b) for(ll i=a;i<b;i++)
#define fi first
#define se second
#define endl "\n"

template<typename T> inline bool chmax(T &a, T b){if(a<b){a=b;return true;}return false;}
template<typename T> inline bool chmin(T &a, T b){if(a>b){a=b;return true;}return false;}
template<typename T> ostream& operator<<(ostream& s,const complex<T>& d) {return s<<"("<<d.real()<<", "<<d.imag()<< ")";}
template<typename T1, typename T2> ostream& operator<<(ostream& s,const pair<T1,T2>& d) {return s<<"("<<d.first<<", "<<d.second<<")";}
template<typename T> ostream& operator<<(ostream& s, const vector<T>& d){int len=d.size();rep(i,len){s<<d[i];if(i<len-1) s<<" ";}return s;}
template<typename T> ostream& operator<<(ostream& s,const vector<vector<T>>& d){int len=d.size();rep(i,len){s<<d[i]<<endl;}return s;}
template<typename T> ostream& operator<<(ostream& s,const set<T>& v){s<<"{ ";for(auto itr=v.begin();itr!=v.end();++itr) {if (itr!=v.begin()) {s<< ", ";}s<<(*itr);}s<<" }";return s;}
template<typename T> ostream& operator<<(ostream& s,const multiset<T>& v){s<<"{ ";for(auto itr=v.begin();itr!=v.end();++itr) {if (itr!=v.begin()) {s<< ", ";}s<<(*itr);}s<<" }";return s;}
template<typename T1, typename T2> ostream& operator<<(ostream& s,const map<T1,T2>& m){s<<"{"<<endl;for(auto itr=m.begin();itr!=m.end();++itr){s<<" "<<(*itr).first<<" : "<<(*itr).second<<endl;}s<<"}"<<endl;return s;}

const ll mod=1'000'000'007;
const ll inf=1'000'000'000'000'000'00;
const int INF=1'000'000'000;
const double EPS=1e-10;
const double PI=acos(-1);

int main(){
	cin.tie(0);ios::sync_with_stdio(false);
	ll n,m;
	cin>>n>>m;
	vector<vector<int>> g(n,vector<int>(m));
	rep(i,n){
		string s;
		cin>>s;
		rep(j,m){
			g[i][j]=int(s[j]-'0');
		}
	}
	if(n>=4 && m>=4){
		cout<<-1<<endl;
		return 0;
	}
	//2*2だけ考えればok
	if(m<=n){
		vector<vector<int>> ng(m,vector<int>(n));
		rep(i,m)rep(j,n){
			ng[i][j]=g[j][i];
		}
		swap(g,ng);
		swap(n,m);
	}
	ll ans=inf;
	if(n==1){
		ans=0;
	}else if(n==2){
		rep(S,1<<4){
			ll now=0;
			vector<vector<int>> ng(g);
			rep(i,4){
				if(S & 1<<i){
					ll x=i/2,y=i-x*2;
					ng[x][y]=!ng[x][y];
					now++;
				}
			}
			int cnt=ng[0][0]+ng[0][0+1]+ng[1][0]+ng[1][0+1];
			if(cnt%2==0) continue;
			FOR(j,1,m-1){
				int cnt=ng[0][j]+ng[0][j+1]+ng[1][j]+ng[1][j+1];
				if(cnt%2) continue;
				now++;
				ng[0][j+1]=!ng[0][j+1];
			}
			chmin(ans,now);
		}
	}else if(n==3){
		rep(S,1<<6){
			ll now=0;
			vector<vector<int>> ng(g);
			rep(i,6){
				if(S & 1<<i){
					ll x=i/2,y=i-x*2;
					ng[x][y]=!ng[x][y];
					now++;
				}
			}
			int cnt1=ng[0][0]+ng[0][0+1]+ng[1][0]+ng[1][0+1];
			int cnt2=ng[2][0]+ng[2][0+1]+ng[1][0]+ng[1][0+1];
			if(cnt1%2==0 || cnt2%2==0) continue;
			FOR(j,1,m-1){
				int cnt1=ng[0][j]+ng[0][j+1]+ng[1][j]+ng[1][j+1];
				int cnt2=ng[2][j]+ng[2][j+1]+ng[1][j]+ng[1][j+1];
				if(cnt1%2 && cnt2%2) continue;
				if(cnt1%2==0){
					if(cnt2%2==0){
						ng[1][j+1]=!ng[1][j+1];
						now++;
					}else{
						ng[0][j+1]=!ng[0][j+1];
						now++;
					}
				}else{
					ng[2][j+1]=!ng[2][j+1];
					now++;
				}
			}
			chmin(ans,now);
		}
	}
	cout<<ans<<endl;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<ll,ll> P;
typedef pair<int,int> Pi;
#define rep(i,n) for(ll i=0;i<n;i++)
#define FOR(i,a,b) for(ll i=a;i<b;i++)
#define fi first
#define se second
#define endl "\n"

template<typename T> inline bool chmax(T &a, T b){if(a<b){a=b;return true;}return false;}
template<typename T> inline bool chmin(T &a, T b){if(a>b){a=b;return true;}return false;}
template<typename T> ostream& operator<<(ostream& s,const complex<T>& d) {return s<<"("<<d.real()<<", "<<d.imag()<< ")";}
template<typename T1, typename T2> ostream& operator<<(ostream& s,const pair<T1,T2>& d) {return s<<"("<<d.first<<", "<<d.second<<")";}
template<typename T> ostream& operator<<(ostream& s, const vector<T>& d){int len=d.size();rep(i,len){s<<d[i];if(i<len-1) s<<" ";}return s;}
template<typename T> ostream& operator<<(ostream& s,const vector<vector<T>>& d){int len=d.size();rep(i,len){s<<d[i]<<endl;}return s;}
template<typename T> ostream& operator<<(ostream& s,const set<T>& v){s<<"{ ";for(auto itr=v.begin();itr!=v.end();++itr) {if (itr!=v.begin()) {s<< ", ";}s<<(*itr);}s<<" }";return s;}
template<typename T> ostream& operator<<(ostream& s,const multiset<T>& v){s<<"{ ";for(auto itr=v.begin();itr!=v.end();++itr) {if (itr!=v.begin()) {s<< ", ";}s<<(*itr);}s<<" }";return s;}
template<typename T1, typename T2> ostream& operator<<(ostream& s,const map<T1,T2>& m){s<<"{"<<endl;for(auto itr=m.begin();itr!=m.end();++itr){s<<" "<<(*itr).first<<" : "<<(*itr).second<<endl;}s<<"}"<<endl;return s;}

const ll mod=1'000'000'007;
const ll inf=1'000'000'000'000'000'00;
const int INF=1'000'000'000;
const double EPS=1e-10;
const double PI=acos(-1);

int main(){
	cin.tie(0);ios::sync_with_stdio(false);
	ll n,m;
	cin>>n>>m;
	vector<vector<int>> g(n,vector<int>(m));
	rep(i,n){
		string s;
		cin>>s;
		rep(j,m){
			g[i][j]=int(s[j]-'0');
		}
	}
	if(n>=4 && m>=4){
		cout<<-1<<endl;
		return 0;
	}
	//2*2だけ考えればok
	if(m<=n){
		vector<vector<int>> ng(m,vector<int>(n));
		rep(i,m)rep(j,n){
			ng[i][j]=g[j][i];
		}
		swap(g,ng);
		swap(n,m);
	}
	ll ans=inf;
	if(n==1){
		cout<<0<<endl;
		return 0;
	}else if(n==2){
		rep(S,1<<4){
			ll now=0;
			vector<vector<int>> ng(g);
			rep(i,4){
				if(S & 1<<i){
					if(i==0) ng[0][0]=!ng[0][0];
					if(i==1) ng[0][1]=!ng[0][1];
					if(i==2) ng[1][0]=!ng[1][0];
					if(i==3) ng[1][1]=!ng[1][1];
					now++;
				}
			}
			int cnt=ng[0][0]+ng[0][0+1]+ng[1][0]+ng[1][0+1];
			if(cnt%2==0) continue;
			FOR(j,1,m-1){
				int cnt=ng[0][j]+ng[0][j+1]+ng[1][j]+ng[1][j+1];
				if(cnt%2) continue;
				now++;
				ng[0][j+1]=!ng[0][j+1];
			}
			chmin(ans,now);
		}
	}else if(n==3){
		rep(S,1<<6){
			ll now=0;
			vector<vector<int>> ng(g);
			rep(i,6){
				if(S & 1<<i){
					if(i==0){
						ng[0][0]=!ng[0][0];
						now++;
					}
					if(i==1){
						ng[0][1]=!ng[0][1];
						now++;
					}
					if(i==2){
						ng[1][0]=!ng[1][0];
						now++;
					}
					if(i==3){
						ng[1][1]=!ng[1][1];
						now++;
					}
					if(i==4){
						ng[2][0]=!ng[2][0];
						now++;
					}
					if(i==5){
						ng[2][1]=!ng[2][1];
						now++;
					}
				}
			}
			int cnt1=ng[0][0]+ng[0][0+1]+ng[1][0]+ng[1][0+1];
			int cnt2=ng[2][0]+ng[2][0+1]+ng[1][0]+ng[1][0+1];
			if(cnt1%2==0 || cnt2%2==0) continue;
			FOR(j,1,m-1){
				int cnt1=ng[0][j]+ng[0][j+1]+ng[1][j]+ng[1][j+1];
				int cnt2=ng[2][j]+ng[2][j+1]+ng[1][j]+ng[1][j+1];
				if(cnt1%2 && cnt2%2) continue;
				if(cnt1%2==0){
					if(cnt2%2==0){
						ng[1][j+1]=!ng[1][j+1];
						now++;
					}else{
						ng[0][j+1]=!ng[0][j+1];
						now++;
					}
				}else{
					ng[2][j+1]=!ng[2][j+1];
					now++;
				}
			}
			chmin(ans,now);
		}
	}
	cout<<ans<<endl;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<ll,ll> P;
typedef pair<int,int> Pi;
#define rep(i,n) for(ll i=0;i<n;i++)
#define FOR(i,a,b) for(ll i=a;i<b;i++)
#define fi first
#define se second
#define endl "\n"

template<typename T> inline bool chmax(T &a, T b){if(a<b){a=b;return true;}return false;}
template<typename T> inline bool chmin(T &a, T b){if(a>b){a=b;return true;}return false;}
template<typename T> ostream& operator<<(ostream& s,const complex<T>& d) {return s<<"("<<d.real()<<", "<<d.imag()<< ")";}
template<typename T1, typename T2> ostream& operator<<(ostream& s,const pair<T1,T2>& d) {return s<<"("<<d.first<<", "<<d.second<<")";}
template<typename T> ostream& operator<<(ostream& s, const vector<T>& d){int len=d.size();rep(i,len){s<<d[i];if(i<len-1) s<<" ";}return s;}
template<typename T> ostream& operator<<(ostream& s,const vector<vector<T>>& d){int len=d.size();rep(i,len){s<<d[i]<<endl;}return s;}
template<typename T> ostream& operator<<(ostream& s,const set<T>& v){s<<"{ ";for(auto itr=v.begin();itr!=v.end();++itr) {if (itr!=v.begin()) {s<< ", ";}s<<(*itr);}s<<" }";return s;}
template<typename T> ostream& operator<<(ostream& s,const multiset<T>& v){s<<"{ ";for(auto itr=v.begin();itr!=v.end();++itr) {if (itr!=v.begin()) {s<< ", ";}s<<(*itr);}s<<" }";return s;}
template<typename T1, typename T2> ostream& operator<<(ostream& s,const map<T1,T2>& m){s<<"{"<<endl;for(auto itr=m.begin();itr!=m.end();++itr){s<<" "<<(*itr).first<<" : "<<(*itr).second<<endl;}s<<"}"<<endl;return s;}

const ll mod=1'000'000'007;
const ll inf=1'000'000'000'000'000'00;
const int INF=1'000'000'000;
const double EPS=1e-10;
const double PI=acos(-1);

int main(){
	cin.tie(0);ios::sync_with_stdio(false);
	ll n,m;
	cin>>n>>m;
	vector<vector<int>> g(n,vector<int>(m));
	rep(i,n){
		string s;
		cin>>s;
		rep(j,m){
			g[i][j]=int(s[j]-'0');
		}
	}
	if(n>=4 && m>=4){
		cout<<-1<<endl;
		return 0;
	}
	//2*2だけ考えればok
	ll ans=0;
	if(m<=n){
		vector<vector<int>> ng(m,vector<int>(n));
		rep(i,m)rep(j,n){
			ng[i][j]=g[j][i];
		}
		swap(g,ng);
		swap(n,m);
	}
	if(n==1){
		cout<<0<<endl;
	}else if(n==2){
		rep(j,m-1){
			int cnt=g[0][j]+g[0][j+1]+g[1][j]+g[1][j+1];
			if(cnt%2) continue;
			ans++;
			if(j==0 && j!=m-2){
				int ne=g[0][j+2]+g[0][j+1]+g[1][j+2]+g[1][j+1];
				if(ne%2==0) g[0][j+1]=!g[0][j+1];
				else g[0][j]=!g[0][j];
			}else{
				g[0][j+1]=!g[0][j+1];
			}
		}
	}else if(n==3){
		rep(j,m-1){
			int cnt1=g[0][j]+g[0][j+1]+g[1][j]+g[1][j+1];
			int cnt2=g[2][j]+g[2][j+1]+g[1][j]+g[1][j+1];
			if(cnt1%2 && cnt2%2) continue;
			if(j==0 && j!=m-2){
				int ne1=g[0][j+2]+g[0][j+1]+g[1][j+2]+g[1][j+1];
				int ne2=g[2][j+2]+g[2][j+1]+g[1][j+2]+g[1][j+1];
				if(cnt1%2==0){
					if(cnt2%2==0){
						if(ne1%2 && ne2%2){
							g[1][j]=!g[1][j];
						}else{
							g[1][j+1]=!g[1][j+1];
						}
						ans++;
					}else{
						if(ne1%2==0) g[0][j+1]=!g[0][j+1];
						else g[0][j]=!g[0][j];
						ans++;
					}
				}else{
					if(ne2%2==0) g[2][j+1]=!g[2][j+1];
					ans++;
				}
			}else{
				if(cnt1%2==0){
					if(cnt2%2==0){
						g[1][j+1]=!g[1][j+1];
						ans++;
					}else{
						g[0][j+1]=!g[0][j+1];
						ans++;
					}
				}else{
					g[2][j+1]=!g[2][j+1];
					ans++;
				}
			}
		}
	}
	cout<<ans<<endl;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<ll,ll> P;
typedef pair<int,int> Pi;
#define rep(i,n) for(ll i=0;i<n;i++)
#define FOR(i,a,b) for(ll i=a;i<b;i++)
#define fi first
#define se second
#define endl "\n"

template<typename T> inline bool chmax(T &a, T b){if(a<b){a=b;return true;}return false;}
template<typename T> inline bool chmin(T &a, T b){if(a>b){a=b;return true;}return false;}
template<typename T> ostream& operator<<(ostream& s,const complex<T>& d) {return s<<"("<<d.real()<<", "<<d.imag()<< ")";}
template<typename T1, typename T2> ostream& operator<<(ostream& s,const pair<T1,T2>& d) {return s<<"("<<d.first<<", "<<d.second<<")";}
template<typename T> ostream& operator<<(ostream& s, const vector<T>& d){int len=d.size();rep(i,len){s<<d[i];if(i<len-1) s<<" ";}return s;}
template<typename T> ostream& operator<<(ostream& s,const vector<vector<T>>& d){int len=d.size();rep(i,len){s<<d[i]<<endl;}return s;}
template<typename T> ostream& operator<<(ostream& s,const set<T>& v){s<<"{ ";for(auto itr=v.begin();itr!=v.end();++itr) {if (itr!=v.begin()) {s<< ", ";}s<<(*itr);}s<<" }";return s;}
template<typename T> ostream& operator<<(ostream& s,const multiset<T>& v){s<<"{ ";for(auto itr=v.begin();itr!=v.end();++itr) {if (itr!=v.begin()) {s<< ", ";}s<<(*itr);}s<<" }";return s;}
template<typename T1, typename T2> ostream& operator<<(ostream& s,const map<T1,T2>& m){s<<"{"<<endl;for(auto itr=m.begin();itr!=m.end();++itr){s<<" "<<(*itr).first<<" : "<<(*itr).second<<endl;}s<<"}"<<endl;return s;}

const ll mod=1'000'000'007;
const ll inf=1'000'000'000'000'000'00;
const int INF=1'000'000'000;
const double EPS=1e-10;
const double PI=acos(-1);

int main(){
	cin.tie(0);ios::sync_with_stdio(false);
	ll n,m;
	cin>>n>>m;
	vector<vector<int>> g(n,vector<int>(m));
	rep(i,n){
		string s;
		cin>>s;
		rep(j,m){
			g[i][j]=int(s[j]-'0');
		}
	}
	if(n>=4 && m>=4){
		cout<<-1<<endl;
		return 0;
	}
	//2*2だけ考えればok
	if(m<=n){
		vector<vector<int>> ng(m,vector<int>(n));
		rep(i,m)rep(j,n){
			ng[i][j]=g[j][i];
		}
		swap(g,ng);
		swap(n,m);
	}
	ll ans=inf;
	if(n==1){
		ans=0;
	}else if(n==2){
		rep(S,1<<4){
			ll now=0;
			vector<vector<int>> tmp(g);
			rep(i,4){
				if(S & 1<<i){
					ll x=i/2,y=i-x*2;
					g[x][y]=!g[x][y];
					now++;
				}
			}
			int cnt=g[0][0]+g[0][0+1]+g[1][0]+g[1][0+1];
			if(cnt%2==0) continue;
			FOR(j,1,m-1){
				int cnt=g[0][j]+g[0][j+1]+g[1][j]+g[1][j+1];
				if(cnt%2) continue;
				now++;
				g[0][j+1]=!g[0][j+1];
			}
			chmin(ans,now);
			swap(tmp,g);
		}
	}else if(n==3){
		rep(S,1<<6){
			ll now=0;
			vector<vector<int>> tmp(g);
			rep(i,6){
				if(S & 1<<i){
					ll x=i/2,y=i-x*2;
					g[x][y]=!g[x][y];
					now++;
				}
			}
			int cnt1=g[0][0]+g[0][0+1]+g[1][0]+g[1][0+1];
			int cnt2=g[2][0]+g[2][0+1]+g[1][0]+g[1][0+1];
			if(cnt1%2==0 || cnt2%2==0) continue;
			FOR(j,1,m-1){
				int cnt1=g[0][j]+g[0][j+1]+g[1][j]+g[1][j+1];
				int cnt2=g[2][j]+g[2][j+1]+g[1][j]+g[1][j+1];
				if(cnt1%2 && cnt2%2) continue;
				if(cnt1%2==0){
					if(cnt2%2==0){
						g[1][j+1]=!g[1][j+1];
						now++;
					}else{
						g[0][j+1]=!g[0][j+1];
						now++;
					}
				}else{
					g[2][j+1]=!g[2][j+1];
					now++;
				}
			}
			chmin(ans,now);
			swap(tmp,g);
		}
	}
	cout<<ans<<endl;
}


#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
typedef pair<ll ,ll> pll;
#define F first
#define S second
#define pb push_back
#define mp make_pair
#define all(X) (X).begin(), (X).end()
#define REP(i,x,y) for(ll i = x;i <= y;++i)
#define fastio ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0)
vector<string> vec_splitter(string s) {
    for(char& c: s) c = c == ','?  ' ': c;
    stringstream ss; ss << s;
    vector<string> res;
    for(string z; ss >> z; res.push_back(z))
        ;
    return res;
}
void debug_out(vector<string> args, int idx) { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(vector<string> args, int idx, Head H, Tail... T) {
    if(idx > 0) cerr << ", ";
    stringstream ss; ss << H;
    cerr << args[idx] << " = " << ss.str();
    debug_out(args, idx + 1, T...);
}
#define debug(...) debug_out(vec_splitter(#__VA_ARGS__), 0, __VA_ARGS__)
void localTest() {
    #ifndef ONLINE_JUDGE
        freopen("inp", "r", stdin);
        freopen("out", "w", stdout);
    #endif
}
const ll N = 1e6 + 5, inf = 1e9;
ll dp[N][8], n, m;
vector<ll> submask[10];
ll doit(vector<vector<ll>> &A, ll idx, ll mask) {
	if(idx > m) return 0;
	ll &ret = dp[idx][mask];
	if(ret != -1) return ret;
	ll curr = 0;
	for(ll j = 1; j <= n; ++j) {
		if(A[j][idx]) curr |= (1LL << (j - 1));
	}
	vector<vector<ll>> aux(n, vector<ll>(2, 0));
	for(ll i = 0; i < n; ++i) {
		if(mask & (1LL << i)) aux[i][0] = 1;
	}
	ll ans = inf;
	for(ll sm = 0; sm < (1LL << n); ++sm) {
		for(ll i = 0; i < n; ++i) {
			if(sm & (1LL << i)) aux[i][1] = 1;
			else {
				aux[i][1] = 0;
			}
		}
		ll c1 = aux[0][0] + aux[0][1] + aux[1][0] + aux[1][1];
		if(c1 % 2 == 0) continue;
		if(n > 2) {
			c1 = aux[1][0] + aux[1][1] + aux[2][0] + aux[2][1];
			if(c1 % 2 == 0) continue;
		}
		ans = min(ans, __builtin_popcount(sm ^ curr) + doit(A, idx + 1, sm));
	}
	return ret = ans;
}
int main() {

    localTest();
    fastio;
 	cin >> n >> m;
 	vector<vector<ll>> A(n + 1, vector<ll>(m + 1, 0));
 	for(ll i = 1; i <= n; ++i) {
 		string s;
 		cin >> s;
 		for(ll j = 1; j <= m; ++j) {
 			if(s[j - 1] == '1') A[i][j] = 1;
 		}
 	}
 	if(n >= 4 && m >= 4) {
 		cout << "-1\n";
 	}
 	else if(n == 1 || m == 1) cout << "0\n";
 	else {
 		memset(dp, -1, sizeof dp);
 		if(n > m) {
 			vector<vector<ll>> B = A;
 			for(ll j = 1; j <= m; ++j) {
 				for(ll i = 1; i <= n; ++i) {
 					B[j][i] = A[i][j];
 				}
 			}
 			swap(n, m);
 			A = B;
 		}
 		ll mask = 0;
		for(ll j = 1; j <= n; ++j) {
			if(A[j][1]) mask |= (1LL << (j - 1));
		}
		ll val = inf;
		for(ll sm = 0; sm < (1LL << n); ++sm) val = min(val, __builtin_popcount(sm ^ mask) + doit(A, 2, sm));
		if(val >= inf) val = -1;
		cout << val << "\n";
 	}

    return 0;
}


#include "bits/stdc++.h"
using namespace std;
typedef int ll;
typedef pair<ll ,ll> pll;
#define F first
#define S second
#define pb push_back
#define mp make_pair
#define all(X) (X).begin(), (X).end()
#define REP(i,x,y) for(ll i = x;i <= y;++i)
#define fastio ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0)
vector<string> vec_splitter(string s) {
    for(char& c: s) c = c == ','?  ' ': c;
    stringstream ss; ss << s;
    vector<string> res;
    for(string z; ss >> z; res.push_back(z))
        ;
    return res;
}
void debug_out(vector<string> args, int idx) { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(vector<string> args, int idx, Head H, Tail... T) {
    if(idx > 0) cerr << ", ";
    stringstream ss; ss << H;
    cerr << args[idx] << " = " << ss.str();
    debug_out(args, idx + 1, T...);
}
#define debug(...) debug_out(vec_splitter(#__VA_ARGS__), 0, __VA_ARGS__)
void localTest() {
    #ifndef ONLINE_JUDGE
        freopen("inp", "r", stdin);
        freopen("out", "w", stdout);
    #endif
}
const ll N = 1e6 + 5, inf = 1e9;
ll dp[N][8], n, m, msk[N];
vector<ll> submask[10];
vector<vector<ll>> A;
ll doit(ll idx, ll mask) {
	if(idx > m) return 0;
	ll &ret = dp[idx][mask];
	if(ret != -1) return ret;
	ll curr = msk[idx];
	vector<vector<ll>> aux(n, vector<ll>(2, 0));
	for(ll i = 0; i < n; ++i) {
		if(mask & (1LL << i)) aux[i][0] = 1;
	}
	ll ans = inf;
	for(ll sm = 0; sm < (1LL << n); ++sm) {
		for(ll i = 0; i < n; ++i) {
			if(sm & (1LL << i)) aux[i][1] = 1;
			else {
				aux[i][1] = 0;
			}
		}
		ll c1 = aux[0][0] + aux[0][1] + aux[1][0] + aux[1][1];
		if(c1 % 2 == 0) continue;
		if(n > 2) {
			c1 = aux[1][0] + aux[1][1] + aux[2][0] + aux[2][1];
			if(c1 % 2 == 0) continue;
		}
		ans = min(ans, __builtin_popcount(sm ^ curr) + doit(idx + 1, sm));
	}
	return ret = ans;
}
int main() {

    localTest();
    fastio;
 	cin >> n >> m;
 	A.resize(n + 1);
 	for(ll i = 1; i <= n; ++i) {
 		string s;
 		cin >> s;
 		A[i].resize(m + 1, 0);
 		for(ll j = 1; j <= m; ++j) {
 			if(s[j - 1] == '1') A[i][j] = 1;
 		}
 	}
 	if(n >= 4 && m >= 4) {
 		cout << "-1\n";
 	}
 	else if(n == 1 || m == 1) cout << "0\n";
 	else {
 		// memset(dp, -1, sizeof dp);
 		if(n > m) {
 			vector<vector<ll>> B = A;
 			for(ll j = 1; j <= m; ++j) {
 				for(ll i = 1; i <= n; ++i) {
 					B[j][i] = A[i][j];
 				}
 			}
 			swap(n, m);
 			A = B;
 		}
 		for(ll i = 1; i <= m; ++i) {
 			ll cur = 0;
	 		for(ll j = 1; j <= n; ++j) {
				if(A[j][i]) cur |= (1LL << (j - 1));
			}
			msk[i] = cur;
		}
 		for(ll i = 1; i <= m; ++i) {
 			for(ll j = 0;j < 8; ++j) dp[i][j] = -1;
 		}
 		ll mask = 0;
		for(ll j = 1; j <= n; ++j) {
			if(A[j][1]) mask |= (1LL << (j - 1));
		}
		ll val = inf;
		for(ll sm = 0; sm < (1LL << n); ++sm) val = min(val, __builtin_popcount(sm ^ mask) + doit(2, sm));
		if(val >= inf) val = -1;
		cout << val << "\n";
 	}

    return 0;
}


#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
typedef pair<ll ,ll> pll;
#define F first
#define S second
#define pb push_back
#define mp make_pair
#define all(X) (X).begin(), (X).end()
#define REP(i,x,y) for(ll i = x;i <= y;++i)
#define fastio ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0)
vector<string> vec_splitter(string s) {
    for(char& c: s) c = c == ','?  ' ': c;
    stringstream ss; ss << s;
    vector<string> res;
    for(string z; ss >> z; res.push_back(z))
        ;
    return res;
}
void debug_out(vector<string> args, int idx) { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(vector<string> args, int idx, Head H, Tail... T) {
    if(idx > 0) cerr << ", ";
    stringstream ss; ss << H;
    cerr << args[idx] << " = " << ss.str();
    debug_out(args, idx + 1, T...);
}
#define debug(...) debug_out(vec_splitter(#__VA_ARGS__), 0, __VA_ARGS__)
void localTest() {
    #ifndef ONLINE_JUDGE
        freopen("inp", "r", stdin);
        freopen("out", "w", stdout);
    #endif
}
const ll N = 1e6 + 5, inf = 1e9;
ll dp[N][10];
vector<ll> submask[10];
ll doit(vector<vector<ll>> &A, ll idx, ll mask, ll n, ll m, ll fl) {
	if(idx > n) return 0;
	ll &ret = dp[idx][mask];
	if(ret != -1) return ret;
	ll curr = 0;
	for(ll j = 1; j <= m; ++j) {
		if(fl) {
			if(A[idx][j]) curr |= (1LL << (j - 1));
		}
		else {
			if(A[j][idx]) curr |= (1LL << (j - 1));
		}
	}
	vector<vector<ll>> aux(m, vector<ll>(2, 0));
	for(ll i = 0; i < 3; ++i) {
		if(mask & (1LL << i)) aux[i][0] = 1;
		else aux[i][0] = 0;
	}
	ll ans = inf;
	for(auto sm : submask[curr]) {
		// debug(idx, mask, sm);
		for(ll i = 0; i < 3; ++i) {
			if(sm & (1LL << i)) aux[i][1] = 1;
			else aux[i][1] = 0;
		}
		// for(ll i = 0; i < m; ++i) {
		// 	for(ll j = 0; j < 2; ++j) debug(i, j, aux[i][j], sm, idx, mask, curr);
		// }
		ll c1 = aux[0][0] + aux[0][1] + aux[1][0] + aux[1][1];
		if(c1 % 2 == 0) continue;
		if(m > 2) {
			c1 = aux[1][0] + aux[1][1] + aux[2][0] + aux[2][1];
			if(c1 % 2 == 0) continue;
		}
		// debug("haha");
		ans = min(ans, __builtin_popcount(sm ^ curr) + doit(A, idx + 1, sm, n, m, fl));
	}
	return ret = ans;
}
int main() {

    localTest();
    fastio;
    for(ll i = 0; i < 10; ++i) {
    	submask[i].pb(0);
    	for(ll j = i; j > 0; j = (i & (j - 1))) submask[i].pb(j);
    }
 	ll n, m;
 	cin >> n >> m;
 	vector<vector<ll>> A(n + 1, vector<ll>(m + 1, 0));
 	for(ll i = 1; i <= n; ++i) {
 		string s;
 		cin >> s;
 		for(ll j = 1; j <= m; ++j) {
 			if(s[j - 1] == '1') A[i][j] = 1;
 		}
 	}
 	if(n >= 4 && m >= 4) {
 		cout << "-1\n";
 	}
 	else if(n == 1 || m == 1) cout << "0\n";
 	else {
 		memset(dp, -1, sizeof dp);
 		if(n > m) {
 			vector<vector<ll>> B;
 			vector<ll> ele(n, 0);
 			B.pb(ele);
 			for(ll j = 1; j <= m; ++j) {
 				vector<ll> aux;
 				aux.pb(0);
 				for(ll i = 1; i <= n; ++i) {
 					aux.pb(A[i][j]);
 				}
 				B.pb(aux);
 			}
 			swap(n, m);
 			A = B;
 		}
 		// for(ll i = 1; i <= n; ++i) {
 		// 	for(ll j = 1; j <= m; ++j) cout << A[i][j];
 		// 	cout << "\n";
 		// }
 		// if(n > m) {
 		// 	ll mask = 0;
 		// 	for(ll j = 1; j <= m; ++j) {
 		// 		if(A[1][j]) mask |= (1LL << (j - 1));
 		// 	}
 		// 	ll val = doit(A, 2, mask, n, m, 1);
 		// 	for(auto sm : submask[mask]) val = min(val, __builtin_popcount(sm ^ mask) + doit(A, 2, sm, n, m, 1));
 		// 	if(val >= inf) val = -1;
 		// 	cout << val << "\n";
 		// } else {
		ll mask = 0;
		for(ll j = 1; j <= n; ++j) {
			if(A[j][1]) mask |= (1LL << (j - 1));
		}
		// debug(mask);
		ll val = inf;
		for(auto sm : submask[mask]) val = min(val, __builtin_popcount(sm ^ mask) + doit(A, 2, sm, m, n, 0));
		if(val >= inf) val = -1;
		cout << val << "\n";
 		// }
 	}

    return 0;
}


#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
typedef pair<ll ,ll> pll;
#define F first
#define S second
#define pb push_back
#define mp make_pair
#define all(X) (X).begin(), (X).end()
#define REP(i,x,y) for(ll i = x;i <= y;++i)
#define fastio ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0)
vector<string> vec_splitter(string s) {
    for(char& c: s) c = c == ','?  ' ': c;
    stringstream ss; ss << s;
    vector<string> res;
    for(string z; ss >> z; res.push_back(z))
        ;
    return res;
}
void debug_out(vector<string> args, int idx) { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(vector<string> args, int idx, Head H, Tail... T) {
    if(idx > 0) cerr << ", ";
    stringstream ss; ss << H;
    cerr << args[idx] << " = " << ss.str();
    debug_out(args, idx + 1, T...);
}
#define debug(...) debug_out(vec_splitter(#__VA_ARGS__), 0, __VA_ARGS__)
void localTest() {
    #ifndef ONLINE_JUDGE
        freopen("inp", "r", stdin);
        freopen("out", "w", stdout);
    #endif
}
const ll N = 1e6 + 5, inf = 1e9;
ll dp[N][8], n, m;
vector<ll> submask[10];
vector<vector<ll>> A;
ll doit(ll idx, ll mask) {
	if(idx > m) return 0;
	ll &ret = dp[idx][mask];
	if(ret != -1) return ret;
	ll curr = 0;
	for(ll j = 1; j <= n; ++j) {
		if(A[j][idx]) curr |= (1LL << (j - 1));
	}
	vector<vector<ll>> aux(n, vector<ll>(2, 0));
	for(ll i = 0; i < n; ++i) {
		if(mask & (1LL << i)) aux[i][0] = 1;
	}
	ll ans = inf;
	for(ll sm = 0; sm < (1LL << n); ++sm) {
		for(ll i = 0; i < n; ++i) {
			if(sm & (1LL << i)) aux[i][1] = 1;
			else {
				aux[i][1] = 0;
			}
		}
		ll c1 = aux[0][0] + aux[0][1] + aux[1][0] + aux[1][1];
		if(c1 % 2 == 0) continue;
		if(n > 2) {
			c1 = aux[1][0] + aux[1][1] + aux[2][0] + aux[2][1];
			if(c1 % 2 == 0) continue;
		}
		ans = min(ans, __builtin_popcount(sm ^ curr) + doit(idx + 1, sm));
	}
	return ret = ans;
}
int main() {

    localTest();
    fastio;
 	cin >> n >> m;
 	A.resize(n + 1);
 	for(ll i = 1; i <= n; ++i) {
 		string s;
 		cin >> s;
 		A[i].resize(m + 1, 0);
 		for(ll j = 1; j <= m; ++j) {
 			if(s[j - 1] == '1') A[i][j] = 1;
 		}
 	}
 	if(n >= 4 && m >= 4) {
 		cout << "-1\n";
 	}
 	else if(n == 1 || m == 1) cout << "0\n";
 	else {
 		memset(dp, -1, sizeof dp);
 		if(n > m) {
 			vector<vector<ll>> B = A;
 			for(ll j = 1; j <= m; ++j) {
 				for(ll i = 1; i <= n; ++i) {
 					B[j][i] = A[i][j];
 				}
 			}
 			swap(n, m);
 			A = B;
 		}
 		ll mask = 0;
		for(ll j = 1; j <= n; ++j) {
			if(A[j][1]) mask |= (1LL << (j - 1));
		}
		ll val = inf;
		for(ll sm = 0; sm < (1LL << n); ++sm) val = min(val, __builtin_popcount(sm ^ mask) + doit(2, sm));
		if(val >= inf) val = -1;
		cout << val << "\n";
 	}

    return 0;
}


#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
typedef pair<ll ,ll> pll;
#define F first
#define S second
#define pb push_back
#define mp make_pair
#define all(X) (X).begin(), (X).end()
#define REP(i,x,y) for(ll i = x;i <= y;++i)
#define fastio ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0)
vector<string> vec_splitter(string s) {
    for(char& c: s) c = c == ','?  ' ': c;
    stringstream ss; ss << s;
    vector<string> res;
    for(string z; ss >> z; res.push_back(z))
        ;
    return res;
}
void debug_out(vector<string> args, int idx) { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(vector<string> args, int idx, Head H, Tail... T) {
    if(idx > 0) cerr << ", ";
    stringstream ss; ss << H;
    cerr << args[idx] << " = " << ss.str();
    debug_out(args, idx + 1, T...);
}
#define debug(...) debug_out(vec_splitter(#__VA_ARGS__), 0, __VA_ARGS__)
void localTest() {
    #ifndef ONLINE_JUDGE
        freopen("inp", "r", stdin);
        freopen("out", "w", stdout);
    #endif
}
const ll N = 1e6 + 5, inf = 1e16;
ll dp[N][10];
vector<ll> submask[10];
ll doit(vector<vector<ll>> &A, ll idx, ll mask, ll n, ll m, ll fl) {
	if(idx > n) return 0;
	ll &ret = dp[idx][mask];
	if(ret != -1) return ret;
	ll curr = 0;
	for(ll j = 1; j <= m; ++j) {
		if(fl) {
			if(A[idx][j]) curr |= (1LL << (j - 1));
		}
		else {
			if(A[j][idx]) curr |= (1LL << (j - 1));
		}
	}
	vector<vector<ll>> aux(m, vector<ll>(2, 0));
	for(ll i = 0; i < 3; ++i) {
		if(mask & (1LL << i)) aux[i][0] = 1;
	}
	ll ans = inf;
	for(auto sm : submask[curr]) {
		// debug(idx, mask, sm);
		for(ll i = 0; i < 3; ++i) {
			if(sm & (1LL << i)) aux[i][1] = 1;
			else aux[i][1] = 0;
		}
		// for(ll i = 0; i < m; ++i) {
		// 	for(ll j = 0; j < 2; ++j) debug(i, j, aux[i][j], sm, idx, mask, curr);
		// }
		ll c1 = aux[0][0] + aux[0][1] + aux[1][0] + aux[1][1];
		if(c1 % 2 == 0) continue;
		if(m > 2) {
			c1 = aux[1][0] + aux[1][1] + aux[2][0] + aux[2][1];
			if(c1 % 2 == 0) continue;
		}
		// debug("haha");
		ans = min(ans, __builtin_popcount(sm ^ curr) + doit(A, idx + 1, sm, n, m, fl));
	}
	return ret = ans;
}
int main() {

    localTest();
    fastio;
    for(ll i = 0; i < 10; ++i) {
    	submask[i].pb(0);
    	for(ll j = i; j > 0; j = (i & (j - 1))) submask[i].pb(j);
    }
 	ll n, m;
 	cin >> n >> m;
 	vector<vector<ll>> A(n + 1, vector<ll>(m + 1, 0));
 	for(ll i = 1; i <= n; ++i) {
 		string s;
 		cin >> s;
 		for(ll j = 1; j <= m; ++j) {
 			if(s[j - 1] == '1') A[i][j] = 1;
 		}
 	}
 	if(n >= 4 && m >= 4) cout << "-1\n";
 	else if(n == 1 || m == 1) cout << "0\n";
 	else {
 		memset(dp, -1, sizeof dp);
 		if(n > m) {
 			ll mask = 0;
 			for(ll j = 1; j <= m; ++j) {
 				if(A[1][j]) mask |= (1LL << (j - 1));
 			}
 			ll val = doit(A, 2, mask, n, m, 1);
 			for(auto sm : submask[mask]) val = min(val, __builtin_popcount(sm ^ mask) + doit(A, 2, sm, n, m, 1));
 			if(val >= inf) val = -1;
 			cout << val << "\n";
 		} else {
 			ll mask = 0;
 			for(ll j = 1; j <= n; ++j) {
 				if(A[j][1]) mask |= (1LL << (j - 1));
 			}
 			// debug(mask);
 			ll val = doit(A, 2, mask, m, n, 0);
 			for(auto sm : submask[mask]) val = min(val, __builtin_popcount(sm ^ mask) + doit(A, 2, sm, m, n, 0));
 			if(val >= inf) val = -1;
 			cout << val << "\n";
 		}
 	}

    return 0;
}


#include "bits/stdc++.h"
using namespace std;
typedef int ll;
typedef pair<ll ,ll> pll;
#define F first
#define S second
#define pb push_back
#define mp make_pair
#define all(X) (X).begin(), (X).end()
#define REP(i,x,y) for(ll i = x;i <= y;++i)
#define fastio ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0)
vector<string> vec_splitter(string s) {
    for(char& c: s) c = c == ','?  ' ': c;
    stringstream ss; ss << s;
    vector<string> res;
    for(string z; ss >> z; res.push_back(z))
        ;
    return res;
}
void debug_out(vector<string> args, int idx) { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(vector<string> args, int idx, Head H, Tail... T) {
    if(idx > 0) cerr << ", ";
    stringstream ss; ss << H;
    cerr << args[idx] << " = " << ss.str();
    debug_out(args, idx + 1, T...);
}
#define debug(...) debug_out(vec_splitter(#__VA_ARGS__), 0, __VA_ARGS__)
void localTest() {
    #ifndef ONLINE_JUDGE
        freopen("inp", "r", stdin);
        freopen("out", "w", stdout);
    #endif
}
const ll N = 1e6 + 5, inf = 1e9;
ll dp[N][8], n, m, msk[N], bit[1000], aux[3][3];
vector<ll> submask[10];
vector<vector<ll>> A;
ll doit(ll idx, ll mask) {
	if(idx > m) return 0;
	ll &ret = dp[idx][mask];
	if(ret != -1) return ret;
	ll curr = msk[idx];
	memset(aux, 0, sizeof aux);
	for(ll i = 0; i < n; ++i) {
		if(mask & (1LL << i)) aux[i][0] = 1;
		else aux[i][0] = 0;
	}
	ll ans = inf;
	for(ll sm = 0; sm < (1LL << n); ++sm) {
		for(ll i = 0; i < n; ++i) {
			if(sm & (1LL << i)) aux[i][1] = 1;
			else aux[i][1] = 0;
		}
		ll c1 = aux[0][0] + aux[0][1] + aux[1][0] + aux[1][1];
		if(c1 % 2 == 0) continue;
		if(n > 2) {
			c1 = aux[1][0] + aux[1][1] + aux[2][0] + aux[2][1];
			if(c1 % 2 == 0) continue;
		}
		ans = min(ans, bit[sm ^ curr] + doit(idx + 1, sm));
	}
	return ret = ans;
}
int main() {

    localTest();
    fastio;
    for(int i = 0; i < 10; ++i) {
    	for(int j = 0; j < 10; ++j) {
    		bit[i ^ j] = __builtin_popcount(i ^ j);
    	}
    }
 	cin >> n >> m;
 	A.resize(n + 1);
 	for(ll i = 1; i <= n; ++i) {
 		string s;
 		cin >> s;
 		A[i].resize(m + 1, 0);
 		for(ll j = 1; j <= m; ++j) {
 			if(s[j - 1] == '1') A[i][j] = 1;
 		}
 	}
 	if(n >= 4 && m >= 4) {
 		cout << "-1\n";
 	}
 	else if(n == 1 || m == 1) cout << "0\n";
 	else {
 		// memset(dp, -1, sizeof dp);
 		// debug(n);
 		if(n > m) {
 			vector<vector<ll>> B = A;
 			for(ll j = 1; j <= m; ++j) {
 				for(ll i = 1; i <= n; ++i) {
 					B[j][i] = A[i][j];
 				}
 			}
 			swap(n, m);
 			A = B;
 		}
 		for(ll i = 1; i <= m; ++i) {
 			ll cur = 0;
	 		for(ll j = 1; j <= n; ++j) {
				if(A[j][i]) cur |= (1LL << (j - 1));
			}
			msk[i] = cur;
		}
 		for(ll i = 1; i <= m; ++i) {
 			for(ll j = 0;j < 8; ++j) dp[i][j] = -1;
 		}
 		ll mask = msk[1];
		ll val = inf;
		// debug(m);
		assert(n <= 3);
		for(ll sm = 0; sm < (1LL << n); ++sm) val = min(val, bit[sm ^ mask] + doit(2, sm));
		if(val >= inf) val = -1;
		cout << val << "\n";
 	}

    return 0;
}


#include "bits/stdc++.h"
using namespace std;
typedef int ll;
typedef pair<ll ,ll> pll;
#define F first
#define S second
#define pb push_back
#define mp make_pair
#define all(X) (X).begin(), (X).end()
#define REP(i,x,y) for(ll i = x;i <= y;++i)
#define fastio ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0)
vector<string> vec_splitter(string s) {
    for(char& c: s) c = c == ','?  ' ': c;
    stringstream ss; ss << s;
    vector<string> res;
    for(string z; ss >> z; res.push_back(z))
        ;
    return res;
}
void debug_out(vector<string> args, int idx) { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(vector<string> args, int idx, Head H, Tail... T) {
    if(idx > 0) cerr << ", ";
    stringstream ss; ss << H;
    cerr << args[idx] << " = " << ss.str();
    debug_out(args, idx + 1, T...);
}
#define debug(...) debug_out(vec_splitter(#__VA_ARGS__), 0, __VA_ARGS__)
void localTest() {
    #ifndef ONLINE_JUDGE
        freopen("inp", "r", stdin);
        freopen("out", "w", stdout);
    #endif
}
const ll N = 1e6 + 5, inf = 1e9;
ll dp[N][8], n, m, msk[N], bit[1000], aux[3][3];
vector<ll> submask[10];
vector<vector<ll>> A;
ll doit(ll idx, ll mask) {
	if(idx > m) return 0;
	ll &ret = dp[idx][mask];
	if(ret != -1) return ret;
	ll curr = msk[idx];
	for(ll i = 0; i < n; ++i) {
		if(mask & (1LL << i)) aux[i][0] = 1;
		else aux[i][0] = 0;
	}
	ll ans = inf;
	for(ll sm = 0; sm < (1LL << n); ++sm) {
		for(ll i = 0; i < n; ++i) {
			if(sm & (1LL << i)) aux[i][1] = 1;
			else aux[i][1] = 0;
		}
		ll c1 = aux[0][0] + aux[0][1] + aux[1][0] + aux[1][1];
		if(c1 % 2 == 0) continue;
		if(n > 2) {
			c1 = aux[1][0] + aux[1][1] + aux[2][0] + aux[2][1];
			if(c1 % 2 == 0) continue;
		}
		ans = min(ans, bit[sm ^ curr] + doit(idx + 1, sm));
	}
	return ret = ans;
}
int main() {

    localTest();
    fastio;
    for(int i = 0; i < 10; ++i) {
    	for(int j = 0; j < 10; ++j) {
    		bit[i ^ j] = __builtin_popcount(i ^ j);
    	}
    }
 	cin >> n >> m;
 	A.resize(n + 1);
 	for(ll i = 1; i <= n; ++i) {
 		string s;
 		cin >> s;
 		A[i].resize(m + 1, 0);
 		for(ll j = 1; j <= m; ++j) {
 			if(s[j - 1] == '1') A[i][j] = 1;
 		}
 	}
 	if(n >= 4 && m >= 4) {
 		cout << "-1\n";
 	}
 	else if(n == 1 || m == 1) cout << "0\n";
 	else {
 		// memset(dp, -1, sizeof dp);
 		// debug(n);
 		if(n > m) {
 			vector<vector<ll>> B = A;
 			for(ll j = 1; j <= m; ++j) {
 				for(ll i = 1; i <= n; ++i) {
 					B[j][i] = A[i][j];
 				}
 			}
 			swap(n, m);
 			A = B;
 		}
 		for(ll i = 1; i <= m; ++i) {
 			ll cur = 0;
	 		for(ll j = 1; j <= n; ++j) {
				if(A[j][i]) cur |= (1LL << (j - 1));
			}
			msk[i] = cur;
		}
 		for(ll i = 1; i <= m; ++i) {
 			for(ll j = 0;j < 8; ++j) dp[i][j] = -1;
 		}
 		ll mask = msk[1];
		ll val = inf;
		// debug(m);
		assert(n <= 3);
		for(ll sm = 0; sm < (1LL << n); ++sm) val = min(val, bit[sm ^ mask] + doit(2, sm));
		if(val >= inf) val = -1;
		cout << val << "\n";
 	}

    return 0;
}


#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
typedef pair<ll ,ll> pll;
#define F first
#define S second
#define pb push_back
#define mp make_pair
#define all(X) (X).begin(), (X).end()
#define REP(i,x,y) for(ll i = x;i <= y;++i)
#define fastio ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0)
vector<string> vec_splitter(string s) {
    for(char& c: s) c = c == ','?  ' ': c;
    stringstream ss; ss << s;
    vector<string> res;
    for(string z; ss >> z; res.push_back(z))
        ;
    return res;
}
void debug_out(vector<string> args, int idx) { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(vector<string> args, int idx, Head H, Tail... T) {
    if(idx > 0) cerr << ", ";
    stringstream ss; ss << H;
    cerr << args[idx] << " = " << ss.str();
    debug_out(args, idx + 1, T...);
}
#define debug(...) debug_out(vec_splitter(#__VA_ARGS__), 0, __VA_ARGS__)
void localTest() {
    #ifndef ONLINE_JUDGE
        freopen("inp", "r", stdin);
        freopen("out", "w", stdout);
    #endif
}
const ll N = 1e6 + 5, inf = 1e16;
ll dp[N][10];
vector<ll> submask[10];
ll doit(vector<vector<ll>> &A, ll idx, ll mask, ll n, ll m, ll fl) {
	if(idx > n) return 0;
	ll &ret = dp[idx][mask];
	if(ret != -1) return ret;
	ll curr = 0;
	for(ll j = 1; j <= m; ++j) {
		if(fl) {
			if(A[idx][j]) curr |= (1LL << (j - 1));
		}
		else {
			if(A[j][idx]) curr |= (1LL << (j - 1));
		}
	}
	vector<vector<ll>> aux(m, vector<ll>(2, 0));
	for(ll i = 0; i < 3; ++i) {
		if(mask & (1LL << i)) aux[i][0] = 1;
		else aux[i][0] = 0;
	}
	ll ans = inf;
	for(auto sm : submask[curr]) {
		// debug(idx, mask, sm);
		for(ll i = 0; i < 3; ++i) {
			if(sm & (1LL << i)) aux[i][1] = 1;
			else aux[i][1] = 0;
		}
		// for(ll i = 0; i < m; ++i) {
		// 	for(ll j = 0; j < 2; ++j) debug(i, j, aux[i][j], sm, idx, mask, curr);
		// }
		ll c1 = aux[0][0] + aux[0][1] + aux[1][0] + aux[1][1];
		if(c1 % 2 == 0) continue;
		if(m > 2) {
			c1 = aux[1][0] + aux[1][1] + aux[2][0] + aux[2][1];
			if(c1 % 2 == 0) continue;
		}
		// debug("haha");
		ans = min(ans, __builtin_popcount(sm ^ curr) + doit(A, idx + 1, sm, n, m, fl));
	}
	return ret = ans;
}
int main() {

    localTest();
    fastio;
    for(ll i = 0; i < 10; ++i) {
    	submask[i].pb(0);
    	for(ll j = i; j > 0; j = (i & (j - 1))) submask[i].pb(j);
    }
 	ll n, m;
 	cin >> n >> m;
 	vector<vector<ll>> A(n + 1, vector<ll>(m + 1, 0));
 	for(ll i = 1; i <= n; ++i) {
 		string s;
 		cin >> s;
 		for(ll j = 1; j <= m; ++j) {
 			if(s[j - 1] == '1') A[i][j] = 1;
 		}
 	}
 	if(n >= 4 && m >= 4) cout << "-1\n";
 	else if(n == 1 || m == 1) cout << "0\n";
 	else {
 		memset(dp, -1, sizeof dp);
 		if(n > m) {
 			vector<vector<ll>> B;
 			vector<ll> ele(n, 0);
 			B.pb(ele);
 			for(ll j = 1; j <= m; ++j) {
 				vector<ll> aux;
 				aux.pb(0);
 				for(ll i = 1; i <= n; ++i) {
 					aux.pb(A[i][j]);
 				}
 				B.pb(aux);
 			}
 			swap(n, m);
 			A = B;
 		}
 		if(n > m) {
 			ll mask = 0;
 			for(ll j = 1; j <= m; ++j) {
 				if(A[1][j]) mask |= (1LL << (j - 1));
 			}
 			ll val = doit(A, 2, mask, n, m, 1);
 			for(auto sm : submask[mask]) val = min(val, __builtin_popcount(sm ^ mask) + doit(A, 2, sm, n, m, 1));
 			if(val >= inf) val = -1;
 			cout << val << "\n";
 		} else {
 			ll mask = 0;
 			for(ll j = 1; j <= n; ++j) {
 				if(A[j][1]) mask |= (1LL << (j - 1));
 			}
 			// debug(mask);
 			ll val = doit(A, 2, mask, m, n, 0);
 			for(auto sm : submask[mask]) val = min(val, __builtin_popcount(sm ^ mask) + doit(A, 2, sm, m, n, 0));
 			if(val >= inf) val = -1;
 			cout << val << "\n";
 		}
 	}

    return 0;
}


#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
typedef pair<ll ,ll> pll;
#define F first
#define S second
#define pb push_back
#define mp make_pair
#define all(X) (X).begin(), (X).end()
#define REP(i,x,y) for(ll i = x;i <= y;++i)
#define fastio ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0)
vector<string> vec_splitter(string s) {
    for(char& c: s) c = c == ','?  ' ': c;
    stringstream ss; ss << s;
    vector<string> res;
    for(string z; ss >> z; res.push_back(z))
        ;
    return res;
}
void debug_out(vector<string> args, int idx) { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(vector<string> args, int idx, Head H, Tail... T) {
    if(idx > 0) cerr << ", ";
    stringstream ss; ss << H;
    cerr << args[idx] << " = " << ss.str();
    debug_out(args, idx + 1, T...);
}
#define debug(...) debug_out(vec_splitter(#__VA_ARGS__), 0, __VA_ARGS__)
void localTest() {
    #ifndef ONLINE_JUDGE
        freopen("inp", "r", stdin);
        freopen("out", "w", stdout);
    #endif
}
const ll N = 1e6 + 5, inf = 1e9;
ll dp[N][8], n, m, msk[N];
vector<ll> submask[10];
vector<vector<ll>> A;
ll doit(ll idx, ll mask) {
	if(idx > m) return 0;
	ll &ret = dp[idx][mask];
	if(ret != -1) return ret;
	ll curr = msk[idx];
	vector<vector<ll>> aux(n, vector<ll>(2, 0));
	for(ll i = 0; i < n; ++i) {
		if(mask & (1LL << i)) aux[i][0] = 1;
	}
	ll ans = inf;
	for(ll sm = 0; sm < (1LL << n); ++sm) {
		for(ll i = 0; i < n; ++i) {
			if(sm & (1LL << i)) aux[i][1] = 1;
			else {
				aux[i][1] = 0;
			}
		}
		ll c1 = aux[0][0] + aux[0][1] + aux[1][0] + aux[1][1];
		if(c1 % 2 == 0) continue;
		if(n > 2) {
			c1 = aux[1][0] + aux[1][1] + aux[2][0] + aux[2][1];
			if(c1 % 2 == 0) continue;
		}
		ans = min(ans, __builtin_popcount(sm ^ curr) + doit(idx + 1, sm));
	}
	return ret = ans;
}
int main() {

    localTest();
    fastio;
 	cin >> n >> m;
 	A.resize(n + 1);
 	for(ll i = 1; i <= n; ++i) {
 		string s;
 		cin >> s;
 		A[i].resize(m + 1, 0);
 		for(ll j = 1; j <= m; ++j) {
 			if(s[j - 1] == '1') A[i][j] = 1;
 		}
 	}
 	if(n >= 4 && m >= 4) {
 		cout << "-1\n";
 	}
 	else if(n == 1 || m == 1) cout << "0\n";
 	else {
 		// memset(dp, -1, sizeof dp);
 		if(n > m) {
 			vector<vector<ll>> B = A;
 			for(ll j = 1; j <= m; ++j) {
 				for(ll i = 1; i <= n; ++i) {
 					B[j][i] = A[i][j];
 				}
 			}
 			swap(n, m);
 			A = B;
 		}
 		for(ll i = 1; i <= m; ++i) {
 			ll cur = 0;
	 		for(ll j = 1; j <= n; ++j) {
				if(A[j][i]) cur |= (1LL << (j - 1));
			}
			msk[i] = cur;
		}
 		for(ll i = 1; i <= m; ++i) {
 			for(ll j = 0;j < 8; ++j) dp[i][j] = -1;
 		}
 		ll mask = 0;
		for(ll j = 1; j <= n; ++j) {
			if(A[j][1]) mask |= (1LL << (j - 1));
		}
		ll val = inf;
		for(ll sm = 0; sm < (1LL << n); ++sm) val = min(val, __builtin_popcount(sm ^ mask) + doit(2, sm));
		if(val >= inf) val = -1;
		cout << val << "\n";
 	}

    return 0;
}


#include "bits/stdc++.h"
using namespace std;
typedef int ll;
typedef pair<ll ,ll> pll;
#define F first
#define S second
#define pb push_back
#define mp make_pair
#define all(X) (X).begin(), (X).end()
#define REP(i,x,y) for(ll i = x;i <= y;++i)
#define fastio ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0)
vector<string> vec_splitter(string s) {
    for(char& c: s) c = c == ','?  ' ': c;
    stringstream ss; ss << s;
    vector<string> res;
    for(string z; ss >> z; res.push_back(z))
        ;
    return res;
}
void debug_out(vector<string> args, int idx) { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(vector<string> args, int idx, Head H, Tail... T) {
    if(idx > 0) cerr << ", ";
    stringstream ss; ss << H;
    cerr << args[idx] << " = " << ss.str();
    debug_out(args, idx + 1, T...);
}
#define debug(...) debug_out(vec_splitter(#__VA_ARGS__), 0, __VA_ARGS__)
void localTest() {
    #ifndef ONLINE_JUDGE
        freopen("inp", "r", stdin);
        freopen("out", "w", stdout);
    #endif
}
const ll N = 1e6 + 5, inf = 1e9;
ll dp[N][8], n, m, msk[N], bit[1000], aux[3][3];
vector<ll> submask[10];
vector<vector<ll>> A;
ll doit(ll idx, ll mask) {
	if(idx > m) return 0;
	ll &ret = dp[idx][mask];
	if(ret != -1) return ret;
	ll curr = msk[idx];
	ll ans = inf;
	for(ll sm = 0; sm < (1LL << n); ++sm) {
		for(ll i = 0; i < n; ++i) {
			if(mask & (1LL << i)) aux[i][0] = 1;
			else aux[i][0] = 0;
			if(sm & (1LL << i)) aux[i][1] = 1;
			else aux[i][1] = 0;
		}
		ll c1 = aux[0][0] + aux[0][1] + aux[1][0] + aux[1][1];
		if(c1 % 2 == 0) continue;
		if(n > 2) {
			c1 = aux[1][0] + aux[1][1] + aux[2][0] + aux[2][1];
			if(c1 % 2 == 0) continue;
		}
		ans = min(ans, bit[sm ^ curr] + doit(idx + 1, sm));
	}
	return ret = ans;
}
int main() {

    localTest();
    fastio;
    for(int i = 0; i < 10; ++i) {
    	for(int j = 0; j < 10; ++j) {
    		bit[i ^ j] = __builtin_popcount(i ^ j);
    	}
    }
 	cin >> n >> m;
 	A.resize(n + 1);
 	for(ll i = 1; i <= n; ++i) {
 		string s;
 		cin >> s;
 		A[i].resize(m + 1, 0);
 		for(ll j = 1; j <= m; ++j) {
 			if(s[j - 1] == '1') A[i][j] = 1;
 		}
 	}
 	if(n >= 4 && m >= 4) {
 		cout << "-1\n";
 	}
 	else if(n == 1 || m == 1) cout << "0\n";
 	else {
 		// memset(dp, -1, sizeof dp);
 		// debug(n);
 		if(n > m) {
 			vector<vector<ll>> B = A;
 			for(ll j = 1; j <= m; ++j) {
 				for(ll i = 1; i <= n; ++i) {
 					B[j][i] = A[i][j];
 				}
 			}
 			swap(n, m);
 			A = B;
 		}
 		for(ll i = 1; i <= m; ++i) {
 			ll cur = 0;
	 		for(ll j = 1; j <= n; ++j) {
				if(A[j][i]) cur |= (1LL << (j - 1));
			}
			msk[i] = cur;
		}
 		for(ll i = 1; i <= m; ++i) {
 			for(ll j = 0;j < 8; ++j) dp[i][j] = -1;
 		}
 		ll mask = msk[1];
		ll val = inf;
		// debug(m);
		assert(n <= 3);
		for(ll sm = 0; sm < (1LL << n); ++sm) val = min(val, bit[sm ^ mask] + doit(2, sm));
		if(val >= inf) val = -1;
		cout << val << "\n";
 	}

    return 0;
}