#include<bits/stdc++.h>
using namespace std;
int n,m;
char str[2000000];
vector<vector<char> > s;
vector<vector<char> > d;
vector<vector<int> > dist;
vector<int> rd;
vector<char> r;
vector<pair<int,int> > q;
char c;
void find_trees(int t) {
    q.clear();
    dist.clear();
    for(int i=0;i<n;i++) {
        rd.clear();
        for(int j=0;j<m;j++) {
            if(s[i][j]=='.') {
                rd.push_back(0);
                q.push_back({i,j});
            }
            else rd.push_back(1e9);
        }
        dist.push_back(rd);
    }
    int ind=0;
    while(ind<q.size()) {
        int x=q[ind].first;
        int y=q[ind].second;
        if(x>0 && dist[x-1][y]>dist[x][y]+1) {
            dist[x-1][y]=dist[x][y]+1;
            q.push_back({x-1,y});
        }
        if(x<n-1 && dist[x+1][y]>dist[x][y]+1) {
            dist[x+1][y]=dist[x][y]+1;
            q.push_back({x+1,y});
        }
        if(y>0 && dist[x][y-1]>dist[x][y]+1) {
            dist[x][y-1]=dist[x][y]+1;
            q.push_back({x,y-1});
        }
        if(y<m-1 && dist[x][y+1]>dist[x][y]+1) {
            dist[x][y+1]=dist[x][y]+1;
            q.push_back({x,y+1});
        }
        if(x>0 && y>0 && dist[x-1][y-1]>dist[x][y]+1) {
            dist[x-1][y-1]=dist[x][y]+1;
            q.push_back({x-1,y-1});
        }
        if(x<n-1 && y<m-1 && dist[x+1][y+1]>dist[x][y]+1) {
            dist[x+1][y+1]=dist[x][y]+1;
            q.push_back({x+1,y+1});
        }
        if(y>0 && x<n-1 && dist[x+1][y-1]>dist[x][y]+1) {
            dist[x+1][y-1]=dist[x][y]+1;
            q.push_back({x+1,y-1});
        }
        if(y<m-1 && x>0 && dist[x-1][y+1]>dist[x][y]+1) {
            dist[x-1][y+1]=dist[x][y]+1;
            q.push_back({x-1,y+1});
        }
        ind++;
    }
    d.clear();
    for(int i=0;i<n;i++) {
        r.clear();
        for(int j=0;j<m;j++) {
            if(s[i][j]=='.') r.push_back('.');
            else {
                if(dist[i][j]>t) r.push_back('X');
                else r.push_back('.');
            }
        }
        d.push_back(r);
    }
}
bool check_fire(int t) {
    q.clear();
    dist.clear();
    for(int i=0;i<n;i++) {
        rd.clear();
        for(int j=0;j<m;j++) {
            if(d[i][j]=='X') {
                rd.push_back(0);
                q.push_back({i,j});
            }
            else rd.push_back(1e9);
        }
        dist.push_back(rd);
    }
    int ind=0;
    while(ind<q.size()) {
        int x=q[ind].first;
        int y=q[ind].second;
        if(x>0 && dist[x-1][y]>dist[x][y]+1) {
            dist[x-1][y]=dist[x][y]+1;
            q.push_back({x-1,y});
        }
        if(x<n-1 && dist[x+1][y]>dist[x][y]+1) {
            dist[x+1][y]=dist[x][y]+1;
            q.push_back({x+1,y});
        }
        if(y>0 && dist[x][y-1]>dist[x][y]+1) {
            dist[x][y-1]=dist[x][y]+1;
            q.push_back({x,y-1});
        }
        if(y<m-1 && dist[x][y+1]>dist[x][y]+1) {
            dist[x][y+1]=dist[x][y]+1;
            q.push_back({x,y+1});
        }
        if(x>0 && y>0 && dist[x-1][y-1]>dist[x][y]+1) {
            dist[x-1][y-1]=dist[x][y]+1;
            q.push_back({x-1,y-1});
        }
        if(x<n-1 && y<m-1 && dist[x+1][y+1]>dist[x][y]+1) {
            dist[x+1][y+1]=dist[x][y]+1;
            q.push_back({x+1,y+1});
        }
        if(y>0 && x<n-1 && dist[x+1][y-1]>dist[x][y]+1) {
            dist[x+1][y-1]=dist[x][y]+1;
            q.push_back({x+1,y-1});
        }
        if(y<m-1 && x>0 && dist[x-1][y+1]>dist[x][y]+1) {
            dist[x-1][y+1]=dist[x][y]+1;
            q.push_back({x-1,y+1});
        }
        ind++;
    }
    for(int i=0;i<n;i++) {
        for(int j=0;j<m;j++) {
            if(s[i][j]=='.' && dist[i][j]<=t) return false;
            if(s[i][j]=='X' && dist[i][j]>t) return false;
        }
    }
    return true;
}
bool pos(int t) {
    find_trees(t);
    return check_fire(t);
}
int main() {
    scanf("%d %d",&n,&m);
    r.clear();
    for(int i=0;i<m+2;i++) r.push_back('.');
    s.push_back(r);
    for(int i=0;i<n;i++) {
        r.clear();
        r.push_back('.');
        scanf("%s",str);
        for(int j=0;j<m;j++) {
            r.push_back(str[j]);
        }
        r.push_back('.');
        s.push_back(r);
    }
    r.clear();
    for(int i=0;i<m+2;i++) r.push_back('.');
    s.push_back(r);
    n+=2;
    m+=2;
    int l=0;
    int r=max(n,m);
    while(l<r) {
        int mid=(l+r+1)>>1;
        if(pos(mid)) l=mid;
        else r=mid-1;
    }
    printf("%d\n",l);
    find_trees(l);
    for(int i=1;i<n-1;i++) {
        for(int j=1;j<m-1;j++) printf("%c",d[i][j]);
        printf("\n");
    }
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
int n,m;
char str[2000000];
vector<vector<char> > s;
vector<vector<char> > d;
vector<vector<int> > dist;
vector<vector<int> > dist2;
vector<int> rd;
vector<char> r;
vector<pair<int,int> > q;
char c;
void bfs() {
    q.clear();
    dist.clear();
    for(int i=0;i<n;i++) {
        rd.clear();
        for(int j=0;j<m;j++) {
            if(s[i][j]=='.') {
                rd.push_back(0);
                q.push_back({i,j});
            }
            else rd.push_back(1e9);
        }
        dist.push_back(rd);
    }
    int ind=0;
    while(ind<q.size()) {
        int x=q[ind].first;
        int y=q[ind].second;
        if(x>0 && dist[x-1][y]>dist[x][y]+1) {
            dist[x-1][y]=dist[x][y]+1;
            q.push_back({x-1,y});
        }
        if(x<n-1 && dist[x+1][y]>dist[x][y]+1) {
            dist[x+1][y]=dist[x][y]+1;
            q.push_back({x+1,y});
        }
        if(y>0 && dist[x][y-1]>dist[x][y]+1) {
            dist[x][y-1]=dist[x][y]+1;
            q.push_back({x,y-1});
        }
        if(y<m-1 && dist[x][y+1]>dist[x][y]+1) {
            dist[x][y+1]=dist[x][y]+1;
            q.push_back({x,y+1});
        }
        if(x>0 && y>0 && dist[x-1][y-1]>dist[x][y]+1) {
            dist[x-1][y-1]=dist[x][y]+1;
            q.push_back({x-1,y-1});
        }
        if(x<n-1 && y<m-1 && dist[x+1][y+1]>dist[x][y]+1) {
            dist[x+1][y+1]=dist[x][y]+1;
            q.push_back({x+1,y+1});
        }
        if(y>0 && x<n-1 && dist[x+1][y-1]>dist[x][y]+1) {
            dist[x+1][y-1]=dist[x][y]+1;
            q.push_back({x+1,y-1});
        }
        if(y<m-1 && x>0 && dist[x-1][y+1]>dist[x][y]+1) {
            dist[x-1][y+1]=dist[x][y]+1;
            q.push_back({x-1,y+1});
        }
        ind++;
    }
}
void find_trees(int t) {
    d.clear();
    for(int i=0;i<n;i++) {
        r.clear();
        for(int j=0;j<m;j++) {
            if(s[i][j]=='.') r.push_back('.');
            else {
                if(dist[i][j]>t) r.push_back('X');
                else r.push_back('.');
            }
        }
        d.push_back(r);
    }
}
bool check_fire(int t) {
    q.clear();
    dist2.clear();
    for(int i=0;i<n;i++) {
        rd.clear();
        for(int j=0;j<m;j++) {
            if(d[i][j]=='X') {
                rd.push_back(0);
                q.push_back({i,j});
            }
            else rd.push_back(1e9);
        }
        dist2.push_back(rd);
    }
    int ind=0;
    while(ind<q.size()) {
        int x=q[ind].first;
        int y=q[ind].second;
        if(s[x][y]=='.' && dist2[x][y]<=t) return false;
        if(s[x][y]=='X' && dist2[x][y]>t) return false;
        if(x>0 && dist2[x-1][y]>dist2[x][y]+1) {
            dist2[x-1][y]=dist2[x][y]+1;
            q.push_back({x-1,y});
        }
        if(x<n-1 && dist2[x+1][y]>dist2[x][y]+1) {
            dist2[x+1][y]=dist2[x][y]+1;
            q.push_back({x+1,y});
        }
        if(y>0 && dist2[x][y-1]>dist2[x][y]+1) {
            dist2[x][y-1]=dist2[x][y]+1;
            q.push_back({x,y-1});
        }
        if(y<m-1 && dist2[x][y+1]>dist2[x][y]+1) {
            dist2[x][y+1]=dist2[x][y]+1;
            q.push_back({x,y+1});
        }
        if(x>0 && y>0 && dist2[x-1][y-1]>dist2[x][y]+1) {
            dist2[x-1][y-1]=dist2[x][y]+1;
            q.push_back({x-1,y-1});
        }
        if(x<n-1 && y<m-1 && dist2[x+1][y+1]>dist2[x][y]+1) {
            dist2[x+1][y+1]=dist2[x][y]+1;
            q.push_back({x+1,y+1});
        }
        if(y>0 && x<n-1 && dist2[x+1][y-1]>dist2[x][y]+1) {
            dist2[x+1][y-1]=dist2[x][y]+1;
            q.push_back({x+1,y-1});
        }
        if(y<m-1 && x>0 && dist2[x-1][y+1]>dist2[x][y]+1) {
            dist2[x-1][y+1]=dist2[x][y]+1;
            q.push_back({x-1,y+1});
        }
        ind++;
    }
    for(int i=0;i<n;i++) {
        for(int j=0;j<m;j++) {
            if(s[i][j]=='.' && dist2[i][j]<=t) return false;
            if(s[i][j]=='X' && dist2[i][j]>t) return false;
        }
    }
    return true;
}
bool pos(int t) {
    find_trees(t);
    return check_fire(t);
}
int main() {
    scanf("%d %d",&n,&m);
    r.clear();
    for(int i=0;i<m+2;i++) r.push_back('.');
    s.push_back(r);
    for(int i=0;i<n;i++) {
        r.clear();
        r.push_back('.');
        scanf("%s",str);
        for(int j=0;j<m;j++) {
            r.push_back(str[j]);
        }
        r.push_back('.');
        s.push_back(r);
    }
    r.clear();
    for(int i=0;i<m+2;i++) r.push_back('.');
    s.push_back(r);
    n+=2;
    m+=2;
    int l=0;
    int r=max(n,m);
    bfs();
    while(l<r) {
        int mid=(l+r+1)>>1;
        if(pos(mid)) l=mid;
        else r=mid-1;
    }
    printf("%d\n",l);
    find_trees(l);
    for(int i=1;i<n-1;i++) {
        for(int j=1;j<m-1;j++) printf("%c",d[i][j]);
        printf("\n");
    }
    return 0;
}


#pragma GCC target ("avx2")
#pragma GCC optimization ("O3")
#pragma GCC optimization ("unroll-loops")

#include <bits/stdc++.h>

using namespace std;

const int N = 1e6 + 5;

int n, m;
vector <vector <char> > a, ans;
vector <vector <int> > f;
vector <vector <char> > ans2;
vector <vector <int> > d;
vector <vector <bool> > inq;
int dx[8] = {-1, -1, -1, 0, 1, 1, 1, 0};
int dy[8] = {-1, 0, 1, 1, 1, 0, -1, -1};

int query (int x1, int y1, int x2, int y2) {
    return f[x2][y2] - f[x1 - 1][y2] - f[x2][y1 - 1] + f[x1 - 1][y1 - 1];
}

bool check (int mid) {
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            ans2[i][j] = '.';
            d[i][j] = (int)1e9 + 2277;
            inq[i][j] = false;
        }
    }

    queue <pair <int, int> > q;
    for (int i = mid + 1; i <= n - mid; i++) {
        for (int j = mid + 1; j <= m - mid; j++) {
            if (a[i][j] == 'X') {
                int x1 = i - mid;
                int y1 = j - mid;
                int x2 = i + mid;
                int y2 = j + mid;
                int res = query(x1, y1, x2, y2);

                if (res == (x2 - x1 + 1) * (y2 - y1 + 1)) {
                    ans2[i][j] = 'X';
                    q.push({i, j});
                    d[i][j] = 0;
                    inq[i][j] = true;
                }
            }
        }
    }

    while (!q.empty()) {
        int x = q.front().first, y = q.front().second; q.pop(); inq[x][y] = false;
        ans2[x][y] = 'X';
        if (d[x][y] == mid) continue;
        for (int i = 0; i < 8; i++) {
            if (x + dx[i] < 1 || x + dx[i] > n || y + dy[i] < 1 || y + dy[i] > m) continue;
            if (d[x + dx[i]][y + dy[i]] > d[x][y] + 1) {
                d[x + dx[i]][y + dy[i]] = d[x][y] + 1;
                if (!inq[x + dx[i]][y + dy[i]]) {
                    q.push({x + dx[i], y + dy[i]});
                    inq[x + dx[i]][y + dy[i]] = true;
                }
            }
        }
    }

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            if (a[i][j] != ans2[i][j]) return false;
        }
    }

    return true;
}

int main(){
    scanf("%d %d", &n, &m); getchar();
    a.assign(n + 2, vector <char>(m + 2, '#'));
    f.assign(n + 2, vector <int>(m + 2, 0));
    ans.assign(n + 2, vector <char>(m + 2, '.'));
    ans2.assign(n + 2, vector <char>(m + 2, '.'));
    d.assign(n + 2, vector <int>(m + 2, (int)1e9 + 2277));
    inq.assign(n + 2, vector <bool>(m + 2, false));
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            a[i][j] = getchar();
            f[i][j] = (a[i][j] == 'X' ? 1 : 0);
        }

        getchar();
    }

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            f[i][j] += f[i - 1][j] + f[i][j - 1] - f[i - 1][j - 1];
        }
    }

    int l = 1, r = 5e5;
    while (l <= r) {
        int mid = (l + r) / 2;
        if (check(mid)) l = mid + 1;
        else r = mid - 1;
    }

    printf("%d\n", r);
    for (int i = r + 1; i <= n - r; i++) {
        for (int j = r + 1; j <= m - r; j++) {
            int x1 = i - r, y1 = j - r;
            int x2 = i + r, y2 = j + r;
            int res = query(x1, y1, x2, y2);

            if (res == (x2 - x1 + 1) * (y2 - y1 + 1)) {
                ans[i][j] = 'X';
            }
        }
    }

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            printf("%c", ans[i][j]);
        }

        puts("");
    }
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int N = 1e6 + 5;

int n, m;
vector <vector <char> > a, ans;
vector <vector <int> > f;

int query (int x1, int y1, int x2, int y2) {
    return f[x2][y2] - f[x1 - 1][y2] - f[x2][y1 - 1] + f[x1 - 1][y1 - 1];
}

bool check (int mid) {
    vector <vector <char> > ans2;
    vector <vector <int> > d;
    ans2.assign(n + 2, vector <char>(m + 2, '.'));
    d.assign(n + 2, vector <int>(m + 2, (int)1e9 + 2277));
    queue <pair <int, int> > q;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            if (a[i][j] == 'X') {
                if (i <= mid || j <= mid || i + mid > n || j + mid > m) continue;
                int x1 = max(i - mid, 1);
                int y1 = max(j - mid, 1);
                int x2 = min(i + mid, n);
                int y2 = min(j + mid, m);
                int res = query(x1, y1, x2, y2);

                if (res == (x2 - x1 + 1) * (y2 - y1 + 1)) {
                    ans2[i][j] = 'X';
                    q.push({i, j});
                    d[i][j] = 0;
                }
            }
        }
    }

    while (!q.empty()) {
        int x = q.front().first, y = q.front().second; q.pop();
        ans2[x][y] = 'X';
        if (d[x][y] == mid) continue;
        for (int dx = -1; dx <= 1; dx++) {
            for (int dy = -1; dy <= 1; dy++) {
                if (dx == 0 && dy == 0) continue;
                if (x + dx < 1 || x + dx > n || y + dy < 1 || y + dy > m) continue;
                if (d[x + dx][y + dy] > d[x][y] + 1) {
                    d[x + dx][y + dy] = d[x][y] + 1;
                    q.push({x + dx, y + dy});
                }
            }
        }
    }

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            if (a[i][j] != ans2[i][j]) return false;
        }
    }

    return true;
}

int main(){
    ios::sync_with_stdio(false);
    cin >> n >> m;
    a.assign(n + 2, vector <char>(m + 2, '#'));
    f.assign(n + 2, vector <int>(m + 2, 0));
    ans.assign(n + 2, vector <char>(m + 2, '.'));
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            cin >> a[i][j];
            f[i][j] = (a[i][j] == 'X' ? 1 : 0);
        }
    }

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            f[i][j] += f[i - 1][j] + f[i][j - 1] - f[i - 1][j - 1];
        }
    }

    int l = 1, r = 1e6;
    while (l <= r) {
        int mid = (l + r) / 2;
        if (check(mid)) l = mid + 1;
        else r = mid - 1;
    }

    cout << r << "\n";
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            if (i <= r || j <= r || i + r > n || j + r > m) continue;
            int x1 = max(1, i - r), y1 = max(1, j - r);
            int x2 = min(n, i + r), y2 = min(m, j + r);
            int res = query(x1, y1, x2, y2);

            if (res == (x2 - x1 + 1) * (y2 - y1 + 1)) {
                ans[i][j] = 'X';
            }
        }
    }

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            cout << ans[i][j];
        }

        cout << "\n";
    }
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int N = 1e6 + 5;

int n, m;
vector <vector <char> > a, ans;
vector <vector <int> > f;

int query (int x1, int y1, int x2, int y2) {
    return f[x2][y2] - f[x1 - 1][y2] - f[x2][y1 - 1] + f[x1 - 1][y1 - 1];
}

bool check (int mid) {
    vector <vector <char> > ans2;
    vector <vector <int> > d;
    ans2.assign(n + 2, vector <char>(m + 2, '.'));
    d.assign(n + 2, vector <int>(m + 2, (int)1e9 + 2277));
    queue <pair <int, int> > q;
    for (int i = mid + 1; i <= n - mid; i++) {
        for (int j = mid + 1; j <= m - mid; j++) {
            if (a[i][j] == 'X') {
                int x1 = i - mid;
                int y1 = j - mid;
                int x2 = i + mid;
                int y2 = j + mid;
                int res = query(x1, y1, x2, y2);

                if (res == (x2 - x1 + 1) * (y2 - y1 + 1)) {
                    ans2[i][j] = 'X';
                    q.push({i, j});
                    d[i][j] = 0;
                }
            }
        }
    }

    while (!q.empty()) {
        int x = q.front().first, y = q.front().second; q.pop();
        ans2[x][y] = 'X';
        if (d[x][y] == mid) continue;
        for (int dx = -1; dx <= 1; dx++) {
            for (int dy = -1; dy <= 1; dy++) {
                if (dx == 0 && dy == 0) continue;
                if (x + dx < 1 || x + dx > n || y + dy < 1 || y + dy > m) continue;
                if (d[x + dx][y + dy] > d[x][y] + 1) {
                    d[x + dx][y + dy] = d[x][y] + 1;
                    q.push({x + dx, y + dy});
                }
            }
        }
    }

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            if (a[i][j] != ans2[i][j]) return false;
        }
    }

    return true;
}

int main(){
    scanf("%d %d", &n, &m); getchar();
    a.assign(n + 2, vector <char>(m + 2, '#'));
    f.assign(n + 2, vector <int>(m + 2, 0));
    ans.assign(n + 2, vector <char>(m + 2, '.'));
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            a[i][j] = getchar();
            f[i][j] = (a[i][j] == 'X' ? 1 : 0);
        }

        getchar();
    }

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            f[i][j] += f[i - 1][j] + f[i][j - 1] - f[i - 1][j - 1];
        }
    }

    int l = 1, r = 1e6;
    while (l <= r) {
        int mid = (l + r) / 2;
        if (check(mid)) l = mid + 1;
        else r = mid - 1;
    }

    printf("%d\n", r);
    for (int i = r + 1; i <= n - r; i++) {
        for (int j = r + 1; j <= m - r; j++) {
            int x1 = i - r, y1 = j - r;
            int x2 = i + r, y2 = j + r;
            int res = query(x1, y1, x2, y2);

            if (res == (x2 - x1 + 1) * (y2 - y1 + 1)) {
                ans[i][j] = 'X';
            }
        }
    }

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            printf("%c", ans[i][j]);
        }

        puts("");
    }
    return 0;
}


#pragma GCC target ("avx2")
#pragma GCC optimization ("O3")
#pragma GCC optimization ("unroll-loops")

#include <bits/stdc++.h>

using namespace std;

const int N = 1e6 + 5;

int n, m;
vector <vector <char> > a, ans;
vector <vector <int> > f;

int query (int x1, int y1, int x2, int y2) {
    return f[x2][y2] - f[x1 - 1][y2] - f[x2][y1 - 1] + f[x1 - 1][y1 - 1];
}

bool check (int mid) {
    vector <vector <char> > ans2;
    vector <vector <int> > d;
    vector <vector <bool> > inq;
    ans2.assign(n + 2, vector <char>(m + 2, '.'));
    d.assign(n + 2, vector <int>(m + 2, (int)1e9 + 2277));
    inq.assign(n + 2, vector <bool>(m + 2, false));
    queue <pair <int, int> > q;
    for (int i = mid + 1; i <= n - mid; i++) {
        for (int j = mid + 1; j <= m - mid; j++) {
            if (a[i][j] == 'X') {
                int x1 = i - mid;
                int y1 = j - mid;
                int x2 = i + mid;
                int y2 = j + mid;
                int res = query(x1, y1, x2, y2);

                if (res == (x2 - x1 + 1) * (y2 - y1 + 1)) {
                    ans2[i][j] = 'X';
                    q.push({i, j});
                    d[i][j] = 0;
                    inq[i][j] = true;
                }
            }
        }
    }

    while (!q.empty()) {
        int x = q.front().first, y = q.front().second; q.pop(); inq[x][y] = false;
        ans2[x][y] = 'X';
        if (d[x][y] == mid) continue;
        for (int dx = -1; dx <= 1; dx++) {
            for (int dy = -1; dy <= 1; dy++) {
                if (dx == 0 && dy == 0) continue;
                if (x + dx < 1 || x + dx > n || y + dy < 1 || y + dy > m) continue;
                if (d[x + dx][y + dy] > d[x][y] + 1) {
                    d[x + dx][y + dy] = d[x][y] + 1;
                    if (!inq[x + dx][y + dy]) {
                        q.push({x + dx, y + dy});
                        inq[x + dx][y + dy] = true;
                    }
                }
            }
        }
    }

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            if (a[i][j] != ans2[i][j]) return false;
        }
    }

    return true;
}

int main(){
    scanf("%d %d", &n, &m); getchar();
    a.assign(n + 2, vector <char>(m + 2, '#'));
    f.assign(n + 2, vector <int>(m + 2, 0));
    ans.assign(n + 2, vector <char>(m + 2, '.'));
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            a[i][j] = getchar();
            f[i][j] = (a[i][j] == 'X' ? 1 : 0);
        }

        getchar();
    }

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            f[i][j] += f[i - 1][j] + f[i][j - 1] - f[i - 1][j - 1];
        }
    }

    int l = 1, r = 5e5;
    while (l <= r) {
        int mid = (l + r) / 2;
        if (check(mid)) l = mid + 1;
        else r = mid - 1;
    }

    printf("%d\n", r);
    for (int i = r + 1; i <= n - r; i++) {
        for (int j = r + 1; j <= m - r; j++) {
            int x1 = i - r, y1 = j - r;
            int x2 = i + r, y2 = j + r;
            int res = query(x1, y1, x2, y2);

            if (res == (x2 - x1 + 1) * (y2 - y1 + 1)) {
                ans[i][j] = 'X';
            }
        }
    }

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            printf("%c", ans[i][j]);
        }

        puts("");
    }
    return 0;
}


#pragma GCC target ("avx2")
#pragma GCC optimization ("O3")
#pragma GCC optimization ("unroll-loops")

#include <bits/stdc++.h>

using namespace std;

const int N = 1e6 + 5;

int n, m;
vector <vector <char> > a, ans;
vector <vector <int> > f;

int query (int x1, int y1, int x2, int y2) {
    return f[x2][y2] - f[x1 - 1][y2] - f[x2][y1 - 1] + f[x1 - 1][y1 - 1];
}

bool check (int mid) {
    vector <vector <char> > ans2;
    vector <vector <int> > d;
    ans2.assign(n + 2, vector <char>(m + 2, '.'));
    d.assign(n + 2, vector <int>(m + 2, (int)1e9 + 2277));
    queue <pair <int, int> > q;
    for (int i = mid + 1; i <= n - mid; i++) {
        for (int j = mid + 1; j <= m - mid; j++) {
            if (a[i][j] == 'X') {
                int x1 = i - mid;
                int y1 = j - mid;
                int x2 = i + mid;
                int y2 = j + mid;
                int res = query(x1, y1, x2, y2);

                if (res == (x2 - x1 + 1) * (y2 - y1 + 1)) {
                    ans2[i][j] = 'X';
                    q.push({i, j});
                    d[i][j] = 0;
                }
            }
        }
    }

    while (!q.empty()) {
        int x = q.front().first, y = q.front().second; q.pop();
        ans2[x][y] = 'X';
        if (d[x][y] == mid) continue;
        for (int dx = -1; dx <= 1; dx++) {
            for (int dy = -1; dy <= 1; dy++) {
                if (dx == 0 && dy == 0) continue;
                if (x + dx < 1 || x + dx > n || y + dy < 1 || y + dy > m) continue;
                if (d[x + dx][y + dy] > d[x][y] + 1) {
                    d[x + dx][y + dy] = d[x][y] + 1;
                    q.push({x + dx, y + dy});
                }
            }
        }
    }

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            if (a[i][j] != ans2[i][j]) return false;
        }
    }

    return true;
}

int main(){
    scanf("%d %d", &n, &m); getchar();
    a.assign(n + 2, vector <char>(m + 2, '#'));
    f.assign(n + 2, vector <int>(m + 2, 0));
    ans.assign(n + 2, vector <char>(m + 2, '.'));
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            a[i][j] = getchar();
            f[i][j] = (a[i][j] == 'X' ? 1 : 0);
        }

        getchar();
    }

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            f[i][j] += f[i - 1][j] + f[i][j - 1] - f[i - 1][j - 1];
        }
    }

    int l = 1, r = 1e6;
    while (l <= r) {
        int mid = (l + r) / 2;
        if (check(mid)) l = mid + 1;
        else r = mid - 1;
    }

    printf("%d\n", r);
    for (int i = r + 1; i <= n - r; i++) {
        for (int j = r + 1; j <= m - r; j++) {
            int x1 = i - r, y1 = j - r;
            int x2 = i + r, y2 = j + r;
            int res = query(x1, y1, x2, y2);

            if (res == (x2 - x1 + 1) * (y2 - y1 + 1)) {
                ans[i][j] = 'X';
            }
        }
    }

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            printf("%c", ans[i][j]);
        }

        puts("");
    }
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define I inline
#define R register
I int read(){
	int x=0;bool f=0;char ch=getchar();
	while(!isdigit(ch))f|=ch=='-',ch=getchar();
	while(isdigit(ch))x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return f?-x:x;
}

I void write(int x){
	if(x<0)putchar('-'),x=-x;
	if(x>9)write(x/10);
	putchar(48+x%10);
}

I void writeln(int x){write(x);putchar('\n');}
I void writebl(int x){write(x);putchar(' ');}

const int maxn = 1e5+5;

int n,m;
struct edge{int v,w,next;}e[maxn<<1];
int head[maxn],ecnt;
#define add(u,v,w) e[++ecnt]=(edge){v,w,head[u]},head[u]=ecnt

bool vis[maxn];
int col[maxn];
void dfs(int u,int Fa,int ty){
	if(vis[u]){
		if(col[u]!=ty)write(0),exit(0);
		return;
	}
	vis[u]=1;col[u]=ty;
	for(R int i=head[u];i;i=e[i].next){
		int v=e[i].v;if(v==Fa)continue;
		dfs(v,u,(e[i].w?ty:-ty));
	}
}

int ksm(int a,int b){int res=1;while(b){if(b&1)res=res*a;b>>=1;a=a*a;}return res;}

signed main(){
	n=read(),m=read();
	for(R int i=1;i<=m;++i){
		int u=read(),v=read(),w=read();
		add(u,v,w);add(v,u,w);
	}
	int ans=0;
	for(R int i=1;i<=n;++i)if(!vis[i])dfs(i,0,1),ans++;
	writeln(ksm(2,ans-1));
}


#include<cstdio>
#include<cstring>
#include<algorithm>
const int mod=1e9+7;
using namespace std;
int fa[100100],val[100100];
int find(int x){
if (fa[x]==x) return x;
int t=find(fa[x]);
val[x]^=val[fa[x]];
return fa[x]=t;}
int main(){
int n,k;
scanf ("%d%d",&n,&k);
for (int i=1;i<=n;i++)fa[i]=i;
for (int i=1;i<=k;i++){
int u,v,w;
scanf ("%d%d%d",&u,&v,&w);w=w^1;
int fu=find(u), fv=find(v);
if (fu!=fv){fa[fv]=fu;val[fv]=val[u]^val[v]^w;}
else{if (w&&!(val[u]^val[v])){puts("0");return 0;}
if (!w&&val[u]^val[v]){puts("0");return 0;}}}
int res=0,ans=1;
for (int i=1;i<=n;i++)if (find(i)==i)res++;
for (int i=1;i<=res-1;i++)ans=(ans*2)%mod;
printf("%d\n",ans);return 0;}


#include <stdio.h>
#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

#define cin Dieulouard
#define cout Houffalize
#define endl '\n'

struct Reader{
	private:
	    static const int BUF_SIZE=1<<22;
	    char BUF_R[BUF_SIZE],*csy1,*csy2;
	    #define GC (csy1==csy2&&(csy2=(csy1=BUF_R)+fread(BUF_R,1,BUF_SIZE,stdin),csy1==csy2)?EOF:*csy1++)
	    #define IL inline
	    template <class T>
	    inline void RI(T &t)
	    {
	    	int u=0;char c=GC;
	    	for (t=0;c<48||c>57;c=GC) {if (c==EOF) return;u=c=='-'?1:0;}
	    	for (;c>47&&c<58;c=GC) t=(t<<1)+(t<<3)+c-48;
	    	t=u?-t:t;
		}
		template <class T>
		inline void RU(T &t)
		{
			char c=GC;for (t=0;c<48||c>57;c=GC) if (c==EOF) return;
			for (;c>47&&c<58;c=GC) t=(t<<1)+(t<<3)+c-48;
		}

    public:
    	IL Reader& operator >> (char &c) {c=GC;return *this;}
    	IL Reader& operator >> (int &t) {RI(t);return *this;}
    	IL Reader& operator >> (ll &t) {RI(t);return *this;}
    	IL Reader& operator >> (char *s)
		{
			char c=GC;
			for (*s=0;c<33;c=GC) if (c==EOF) return *this;
			for (;c>32;c=GC) *s++=c;
			*s=0;return *this;
		}
    	#ifdef _GLIBCXX_STRING
    	IL Reader& operator >> (string s)
    	{
    		char c=GC;
    		for (s.clear();c<33;c=GC) if (c==EOF) return *this;
    		for (;c>32;c=GC) s+=c;
    		return *this;
		}
		#endif
}cin;
struct Writer{
	private:
	    static const int BUF_SIZE=1<<22;
	    char BUF_W[BUF_SIZE],*csy;
	    #define IL inline
		inline void WC(const char c)
		{
			if (csy-BUF_W==BUF_SIZE) fwrite(BUF_W,1,BUF_SIZE,stdout),csy=BUF_W;
			*csy++=c;
		}
		template <class T>
		inline void WI(T x)
		{
			static int sta[38];
			int top=0;
			if (x<0) {
				WC('-');do sta[top++]=-(x%10); while (x/=10);
			}else do sta[top++]=x%10; while (x/=10);
			while (top) WC(sta[--top]+'0');
		}

	public:
		Writer() : csy(BUF_W) {}
		~Writer() {fwrite(BUF_W,1,csy-BUF_W,stdout);}
		IL void flush() {fwrite(BUF_W,1,csy-BUF_W,stdout);csy=BUF_W;}
		IL Writer& operator << (const char c) {WC(c);return *this;}
		IL Writer& operator << (int x) {WI(x);return *this;}
		IL Writer& operator << (ll x) {WI(x);return *this;}
		IL Writer& operator << (const char *s) {while (*s) WC(*s++);return *this;}
		#ifdef _GLIBCXX_STRING
    	IL Writer& operator << (string s) {for (int i=0;i<s.size();++i) WC(s[i]);return *this;}
		#endif
}cout;

const int mod=1e9+7;
int power(int a,int n)
{
	int ans=1;
	a%=mod;
	while (n) {
		if (n&1) ans=1ll*ans*a%mod;
		a=1ll*a*a%mod;
		n>>=1;
	}
	return ans;
}

const int N=100005;
int n,m,fath[N],dis[N];

inline int Find(int x)
{
	if (fath[x]==x) return x;
	int d=Find(fath[x]);
	dis[x]=dis[x]?dis[fath[x]]:dis[fath[x]]^1;
	return fath[x]=d;
}

inline bool Merge(int a,int b,bool rel)
{
	int x=Find(a),y=Find(b);
	if (x==y) {
		int t=dis[a]+dis[b];
		if (t&1) t=0;
		else t=1;
		return t!=rel;
	}
	fath[x]=y;
	dis[x]=dis[a]==dis[b]?rel:1^rel;
	return 0;
}

int main()
{
	cin>>n>>m;
	for (int i=1;i<=n;++i) {
		fath[i]=i;
	}
	for (int i=1;i<=m;++i) {
		int x,y,z;
		cin>>x>>y>>z;
		if (Merge(x,y,z)) {
			cout<<0<<endl;
			return 0;
		}
	}

	int cnt=0;
	for (int i=1;i<=n;++i) {
		if (fath[i]==i) cnt++;
	}
	cout<<power(2,cnt-1)<<endl;

	return 0;
}


#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#define ll long long
#define re register
#define il inline
#define fp(i,a,b) for(re int i=a;i<=b;++i)
#define fq(i,a,b) for(re int i=a;i>=b;--i)
using namespace std;
const int N=1e5+100,mod=1e9+7;
int n,m,h[N],cnt,ans,col[N];
bool vis[N];
struct Edge{int to,nxt,w;}e[N<<1];
il void add(re int u,re int v,re int w){e[++cnt]=(Edge){v,h[u],w};h[u]=cnt;}
il ll gi()
{
  re ll x=0,t=1;
  re char ch=getchar();
  while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
  if(ch=='-') t=-1,ch=getchar();
  while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
  return x*t;
}
il void dfs(re int u)
{
  vis[u]=1;
  for(re int i=h[u];i+1;i=e[i].nxt)
    {
      re int v=e[i].to,g=col[u]^e[i].w;
      if(vis[v]) {if(g^col[v]) {puts("0");exit(0);}}
      else col[v]=g,dfs(v);
    }
}
int main()
{
  memset(h,-1,sizeof(h));
  n=gi();m=gi();
  fp(i,1,m)
    {
      re int u=gi(),v=gi(),w=gi()^1;
      add(u,v,w);add(v,u,w);
    }
  fp(i,1,n)
    if(!vis[i])
      {
	dfs(i);
	if(!ans) ans=1;else ans=1ll*ans*2%mod;
      }
  printf("%d\n",ans);
  return 0;
}


/*
    Author: Zhouxing Shi
    Created on Jun25, 2015
*/
#include <bits/stdc++.h>
#define rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define drep(i, a, b) for (int i = (a); i >= (b); --i)
#define REP(i, a, b) for (int i = (a); i < (b); ++i)
#define pb(x) push_back(x)
#define mp(x, y) (make_pair(x, y))
#define clr(x) memset(x, 0, sizeof(x))
#define xx first
#define yy second

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
const int inf = ~0U >> 1;
const ll INF = ~0ULL >> 1;
//***************************

const int maxn = 200000;
const int mo = 1000000007;

int N, M, f[maxn], u[maxn], v[maxn], c[maxn], cnt, ans = 1, vis[maxn];
int col[maxn];
vector<int> E[maxn];

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

void dfs(int u, int c)
{
	vis[u] = 1;
	col[u] = c;
	for (auto v:E[u])
		if (!col[v]) dfs(v, 1 - c);
		else if (col[v] != 1 - c)
		{
			puts("0");
			exit(0);
		}
}

int main()
{
	scanf("%d%d", &N, &M);
	rep(i, 1, N) f[i] = i;
	rep(i, 1, M)
	{
		scanf("%d%d%d", &u[i], &v[i], &c[i]);
		if (c[i])
			f[find(u[i])] = find(v[i]);
	}
	rep(i, 1, M)
		if (!c[i])
			E[find(u[i])].pb(find(v[i]));
	rep(i, 1, N)
		if (find(i) == i)
		{
			if (!vis[i])
			{
				dfs(i, 0);
				cnt++;
			}
		}
	rep(i, 1, cnt - 1) ans = ans * 2 % mo;
	printf("%d\n", ans);
    return 0;
}


/*
    Author: Zhouxing Shi
    Created on Jun25, 2015
*/
#include <bits/stdc++.h>
#define rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define drep(i, a, b) for (int i = (a); i >= (b); --i)
#define REP(i, a, b) for (int i = (a); i < (b); ++i)
#define pb(x) push_back(x)
#define mp(x, y) (make_pair(x, y))
#define clr(x) memset(x, 0, sizeof(x))
#define xx first
#define yy second

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
const int inf = ~0U >> 1;
const ll INF = ~0ULL >> 1;
//***************************

const int maxn = 200000;
const int mo = 1000000007;

int N, M, f[maxn], u[maxn], v[maxn], c[maxn], cnt, ans = 1, vis[maxn];
int col[maxn];
vector<int> E[maxn];

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

void dfs(int u, int c)
{
	vis[u] = 1;
	col[u] = c;
	for (auto v:E[u])
		if (!vis[v]) dfs(v, 1 - c);
		else if (col[v] != 1 - c)
		{
			puts("0");
			exit(0);
		}
}

int main()
{
	scanf("%d%d", &N, &M);
	rep(i, 1, N) f[i] = i;
	rep(i, 1, M)
	{
		scanf("%d%d%d", &u[i], &v[i], &c[i]);
		if (c[i])
			f[find(u[i])] = find(v[i]);
	}
	rep(i, 1, M)
		if (!c[i])
		{
			E[find(u[i])].pb(find(v[i]));
			E[find(v[i])].pb(find(u[i]));
		}
	rep(i, 1, N)
		if (find(i) == i)
		{
			if (!vis[i])
			{
				dfs(i, 0);
				cnt++;
			}
		}
	rep(i, 1, cnt - 1) ans = ans * 2 % mo;
	printf("%d\n", ans);
    return 0;
}


/*
    Author: Zhouxing Shi
    Created on Jun25, 2015
*/
#include <bits/stdc++.h>
#define rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define drep(i, a, b) for (int i = (a); i >= (b); --i)
#define REP(i, a, b) for (int i = (a); i < (b); ++i)
#define pb(x) push_back(x)
#define mp(x, y) (make_pair(x, y))
#define clr(x) memset(x, 0, sizeof(x))
#define xx first
#define yy second

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
const int inf = ~0U >> 1;
const ll INF = ~0ULL >> 1;
//***************************

const int maxn = 200000;
const int mo = 1000000007;

int N, M, f[maxn], u[maxn], v[maxn], c[maxn], cnt, ans = 1, vis[maxn];
int col[maxn];
vector<int> E[maxn];

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

void dfs(int u, int c)
{
	vis[u] = 1;
	col[u] = c;
	for (auto v:E[u])
		if (!col[v]) dfs(v, 1 - c);
		else if (col[v] != 1 - c)
		{
			puts("0");
			exit(0);
		}
}

int main()
{
	scanf("%d%d", &N, &M);
	rep(i, 1, N) f[i] = i;
	rep(i, 1, M)
	{
		scanf("%d%d%d", &u[i], &v[i], &c[i]);
		if (c[i])
			f[find(u[i])] = find(v[i]);
	}
	rep(i, 1, M)
		if (!c[i])
		{
			E[find(u[i])].pb(find(v[i]));
			E[find(v[i])].pb(find(u[i]));
		}
	rep(i, 1, N)
		if (find(i) == i)
		{
			if (!vis[i])
			{
				dfs(i, 0);
				cnt++;
			}
		}
	rep(i, 1, cnt - 1) ans = ans * 2 % mo;
	printf("%d\n", ans);
    return 0;
}


#include<stdio.h>
#include <algorithm>
#include <vector>
#include <string>
#include <math.h>
#include <queue>
#include <string.h>
#include <iostream>
// #include <unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<int,char> pic;
#define pb push_back
#define mkp make_pair
#define st first
#define sd second
// const ll INF = 0x3f3f3f3f3f3f3f;
const double esp = 1e-9;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f;
//!!!!!!!!!!!!!!!!!!!!!!!!
const int mod = 1e9+7;
const int maxn = 1e5 + 21;

int fa[maxn];
int vis[maxn];
int findx(int x)
{
	if(fa[x] == x)
		return x;
	int t = fa[x];
	fa[x] = findx(fa[x]);
	vis[x] ^= vis[t];
	return fa[x];
}
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	for (int  i= 1; i<= n; i ++ )
		fa[i] = i;
	int f = 0;
	for (int i =1 ;i<= m; i ++ )
	{
		int x,y,val;
		scanf("%d%d%d",&x,&y,&val);
		val ^= 1;
		int xx = findx(x);
		int yy = findx(y);
		if(fa[xx] == yy)
		{
			if(vis[x] ^ vis[y] != val)
			{
				f = 1;
			}
			continue;
		}
		fa[xx] = yy;
		vis[xx] = val;
	}
	if(f)
	{
		printf("0\n");
		return 0;
	}
	ll ans = 1;
	for (int i = 1; i<= n; i ++ )
	{

		if(fa[i] == i)
		{
			if(f)
				ans = ans * 2 % mod;
			f = 1;
		}
	}
	printf("%lld\n",ans);
}


#include<stdio.h>
#include <algorithm>
#include <vector>
#include <string>
#include <math.h>
#include <queue>
#include <string.h>
#include <iostream>
// #include <unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<int,char> pic;
#define pb push_back
#define mkp make_pair
#define st first
#define sd second
// const ll INF = 0x3f3f3f3f3f3f3f;
const double esp = 1e-9;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f;
//!!!!!!!!!!!!!!!!!!!!!!!!
const int mod = 1e9+7;
const int maxn = 1e5 + 21;

int fa[maxn];
int vis[maxn];
int findx(int x)
{
	if(fa[x] == x)
		return x;
	int t = fa[x];
	fa[x] = findx(fa[x]);
	vis[x] ^= vis[t];
	return fa[x];
}
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	for (int  i= 1; i<= n; i ++ )
		fa[i] = i;
	int f = 0;
	for (int i =1 ;i<= m; i ++ )
	{
		int x,y,val;
		scanf("%d%d%d",&x,&y,&val);
		val ^= 1;
		int xx = findx(x);
		int yy = findx(y);
		if(fa[xx] == yy)
		{
			if(vis[x] ^ vis[y] != val)
			{
				f = 1;
			}
			continue;
		}
		fa[xx] = yy;
		vis[xx] = vis[x] ^ vis[y] ^ val;
	}
	if(f)
	{
		printf("0\n");
		return 0;
	}
	ll ans = 1;
	for (int i = 1; i<= n; i ++ )
	{

		if(fa[i] == i)
		{
			if(f)
				ans = ans * 2 % mod;
			f = 1;
		}
	}
	printf("%lld\n",ans);
}


#include<stdio.h>
#include <algorithm>
#include <vector>
#include <string>
#include <math.h>
#include <queue>
#include <string.h>
#include <iostream>
// #include <unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<int,char> pic;
#define pb push_back
#define mkp make_pair
#define st first
#define sd second
// const ll INF = 0x3f3f3f3f3f3f3f;
const double esp = 1e-9;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f;
//!!!!!!!!!!!!!!!!!!!!!!!!
const int mod = 1e9+7;
const int maxn = 1000 + 21;

int fa[maxn];
int vis[maxn];
int findx(int x)
{
	if(fa[x] == x)
		return x;
	int t = fa[x];
	fa[x] = findx(fa[x]);
	vis[x] ^= vis[t];
	return fa[x];
}
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	for (int  i= 1; i<= n; i ++ )
		fa[i] = i;
	int f = 0;
	for (int i =1 ;i<= m; i ++ )
	{
		int x,y,val;
		scanf("%d%d%d",&x,&y,&val);
		val ^= 1;
		int xx = findx(x);
		int yy = findx(y);
		if(fa[xx] == yy)
		{
			if(vis[x] ^ vis[y] != val)
			{
				f = 1;
			}
			continue;
		}
		fa[xx] = yy;
		vis[xx] = val;
	}
	if(f)
	{
		printf("0\n");
		return 0;
	}
	ll ans = 1;
	for (int i = 1; i<= n; i ++ )
	{

		if(fa[i] == i)
		{
			if(f)
				ans = ans * 2 % mod;
			f = 1;
		}
	}
	printf("%lld\n",ans);
}


#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<map>
#include<string>
#include<utility>
#include<iomanip>

using namespace std;

typedef long long ll;
const ll max_n = 3 * 1e5;
vector<ll> vec[max_n];
vector<pair<ll , ll>> hates;
ll a , b , n , m , type , g , l;
ll col[max_n];
const ll q = 1e9 + 7;
bool flag;

void dfs(ll v , ll comp , ll t , bool y){
    if (t == 1) col[v] = comp;
    else    col[v] = ll(y) + 1;
    for (ll i = 0 ; i < vec[v].size() ; i++){
	 if (col[vec[v][i]] == 0)	 dfs(vec[v][i] , comp , t , !y);
	 else	  if (t == 2 && col[v] == col[vec[v][i]])   flag = 1;
	 if (flag)   return;
    }
}

void run_dfs(ll t){
    for (ll i = 0 ; i < n ; i++){
	 if (col[i])	   continue;
	 if (t == 1 || n <= l)   g++;
	 dfs(i , g , t , 0);
	 if (flag)   return;
    }
}

int main(){
    cin >> n >> m;
    for (ll i = 0 ; i < m ; i++){
	 cin >> a >> b >> type;
	 a--;	  b--;
	 if (a > b)  swap(a , b);
	 if (type == 1){
	     vec[a].push_back(b);
	     vec[b].push_back(a);
	 }
	 else	  hates.push_back({a , b});
    }
    run_dfs(1);
    for (ll i = 0 ; i < n ; i++)
	 vec[i].clear();
    for (ll i = 0 ; i < hates.size() ; i++){
	 pair<ll , ll> temp = hates[i];
	 if (col[temp.first] == col[temp.second]){
	     cout << 0 << endl;
	     return  0;
	 }
	 vec[col[temp.first]].push_back(col[temp.second]);
	 vec[col[temp.second]].push_back(col[temp.first]);
    }
    for (ll i = 0 ; i < n ; i++)
	 col[i] = 0;
    l = g;
    g = 0;
    run_dfs(2);
    if (flag){
	 cout << 0 << endl;
	 return  0;
    }
    ll ans = 1;
    for (ll i = 0 ; i < g - 1 ; i++){
	 ans *= 2;
	 ans %= q;
    }
    cout << ans << endl;
    return 0;
}


#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<map>
#include<string>
#include<utility>
#include<iomanip>

using namespace std;

typedef long long ll;
const ll max_n = 3 * 1e5;
vector<ll> vec[max_n];
vector<pair<ll , ll>> hates;
ll a , b , n , m , type , g , l;
ll col[max_n];
const ll q = 1e9 + 7;
bool flag;

void dfs(ll v , ll comp , ll t , bool y){
    if (t == 1) col[v] = comp;
    else    col[v] = ll(y) + 1;
    for (ll i = 0 ; i < vec[v].size() ; i++){
	 if (col[vec[v][i]] == 0)	 dfs(vec[v][i] , comp , t , !y);
	 else	  if (t == 2 && col[v] == col[vec[v][i]])   flag = 1;
	 if (flag)   return;
    }
}

void run_dfs(ll t){
    for (ll i = 0 ; i <= n ; i++){
	 if (t == 1 && i == n)   continue;
	 if (t == 2 && (i == 0 || i > l))  continue;
	 if (col[i])	   continue;
	 g++;
	 dfs(i , g , t , 0);
	 if (flag)   return;
    }
}

int main(){
    cin >> n >> m;
    for (ll i = 0 ; i < m ; i++){
	 cin >> a >> b >> type;
	 a--;	  b--;
	 if (a > b)  swap(a , b);
	 if (type == 1){
	     vec[a].push_back(b);
	     vec[b].push_back(a);
	 }
	 else	  hates.push_back({a , b});
    }
    run_dfs(1);
    for (ll i = 0 ; i < n ; i++)
	 vec[i].clear();
    for (ll i = 0 ; i < hates.size() ; i++){
	 pair<ll , ll> temp = hates[i];
	 if (col[temp.first] == col[temp.second]){
	     cout << 0 << endl;
	     return  0;
	 }
	 vec[col[temp.first]].push_back(col[temp.second]);
	 vec[col[temp.second]].push_back(col[temp.first]);
    }
    for (ll i = 0 ; i < n + 5 ; i++)
	 col[i] = 0;
    l = g;
    g = 0;
    run_dfs(2);
    if (flag){
	 cout << 0 << endl;
	 return  0;
    }
    ll ans = 1;
    for (ll i = 0 ; i < g - 1 ; i++){
	 ans *= 2;
	 ans %= q;
    }
    cout << ans << endl;
    return 0;
}


#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<map>
#include<string>
#include<utility>
#include<iomanip>

using namespace std;

typedef long long ll;
const ll max_n = 3 * 1e5;
vector<ll> vec[max_n];
vector<pair<ll , ll>> hates;
ll a , b , n , m , type , g;
ll col[max_n];
const ll q = 1e9 + 7;

void dfs(ll v , ll comp){
    if (col[v])    return;
    col[v] = comp;
    for (ll i = 0 ; i < vec[v].size() ; i++)
	 dfs(vec[v][i] , comp);
}

void run_dfs(){
    for (ll i = 0 ; i < n ; i++){
	 if (col[i])	   continue;
	 g++;
	 dfs(i , g);
    }
}

int main(){
    cin >> n >> m;
    for (ll i = 0 ; i < m ; i++){
	 cin >> a >> b >> type;
	 a--;	  b--;
	 if (type == 1){
	     vec[a].push_back(b);
	     vec[b].push_back(a);
	 }
	 else	  hates.push_back({a , b});
    }
    run_dfs();
    for (ll i = 0 ; i < hates.size() ; i++){
	 pair<ll , ll> temp = hates[i];
	 if (col[temp.first] == col[temp.second]){
	     cout << 0 << endl;
	     return  0;
	 }
	 else	  g--;
    }
    ll ans = 1;
    for (ll i = 0 ; i < g - 1 ; i++){
	 ans *= 2;
	 ans %= q;
    }
    cout << ans << endl;
    return 0;
}


#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<map>
#include<string>
#include<utility>
#include<iomanip>

using namespace std;

typedef long long ll;
const ll max_n = 3 * 1e5;
vector<ll> vec[max_n];
vector<pair<ll , ll>> hates;
ll a , b , n , m , type , g;
ll col[max_n];
const ll q = 1e9 + 7;
bool flag;

void dfs(ll v , ll comp , int t , bool y){
    if (t == 1) col[v] = comp;
    else    col[v] = int(y) + 1;
    for (ll i = 0 ; i < vec[v].size() ; i++){
	 if (col[vec[v][i]] == 0)	 dfs(vec[v][i] , comp , t , !y);
	 else	  if (t == 2 && col[v] == col[vec[v][i]])   flag = 1;
	 if (flag)   return;
    }
}

void run_dfs(int t){
    for (ll i = 0 ; i < n ; i++){
	 if (col[i])	   continue;
	 if (t == 1) g++;
	 dfs(i , g , t , 0);
	 if (flag)   return;
    }
}

int main(){
    cin >> n >> m;
    for (ll i = 0 ; i < m ; i++){
	 cin >> a >> b >> type;
	 a--;	  b--;
	 if (type == 1){
	     vec[a].push_back(b);
	     vec[b].push_back(a);
	 }
	 else	  hates.push_back({a , b});
    }
    run_dfs(1);
    for (int i = 0 ; i < n ; i++)
	 vec[i].clear();
    for (ll i = 0 ; i < hates.size() ; i++){
	 pair<ll , ll> temp = hates[i];
	 if (col[temp.first] == col[temp.second]){
	     cout << 0 << endl;
	     return  0;
	 }
	 g--;
	 vec[temp.first].push_back(temp.second);
	 vec[temp.second].push_back(temp.first);
    }
    for (int i = 0 ; i < n ; i++)
	 col[i] = 0;
    run_dfs(2);
    if (flag){
	 cout << 0 << endl;
	 return  0;
    }
    ll ans = 1;
    for (ll i = 0 ; i < g - 1 ; i++){
	 ans *= 2;
	 ans %= q;
    }
    cout << ans << endl;
    return 0;
}


#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<map>
#include<string>
#include<utility>
#include<iomanip>

using namespace std;

typedef long long ll;

struct Thing{
    ll first , second;
};

bool operator <(Thing a , Thing b){
    if (a.first < b.first)	return	 true;
    if (a.first == b.first && a.second < b.second)  return  true;
    return  false;
}

const ll max_n = 3 * 1e5;
vector<ll> vec[max_n];
vector<pair<ll , ll>> hates;
ll a , b , n , m , type , g;
ll col[max_n];
const ll q = 1e9 + 7;
bool flag;
set<Thing>	   st;

void dfs(ll v , ll comp , ll t , bool y){
    if (t == 1) col[v] = comp;
    else    col[v] = ll(y) + 1;
    for (ll i = 0 ; i < vec[v].size() ; i++){
	 if (col[vec[v][i]] == 0)	 dfs(vec[v][i] , comp , t , !y);
	 else	  if (t == 2 && col[v] == col[vec[v][i]])   flag = 1;
	 if (flag)   return;
    }
}

void run_dfs(ll t){
    for (ll i = 0 ; i < n ; i++){
	 if (col[i])	   continue;
	 if (t == 1) g++;
	 dfs(i , g , t , 0);
	 if (flag)   return;
    }
}

int main(){
    cin >> n >> m;
    for (ll i = 0 ; i < m ; i++){
	 cin >> a >> b >> type;
	 a--;	  b--;
	 if (a > b)  swap(a , b);
	 if (type == 1){
	     vec[a].push_back(b);
	     vec[b].push_back(a);
	 }
	 else	  hates.push_back({a , b});
    }
    run_dfs(1);
    for (ll i = 0 ; i < n ; i++)
	 vec[i].clear();
    Thing tz;
    for (ll i = 0 ; i < hates.size() ; i++){
	 pair<ll , ll> temp = hates[i];
	 if (col[temp.first] == col[temp.second]){
	     cout << 0 << endl;
	     return  0;
	 }
	 tz.first = col[temp.first];	 tz.second = col[temp.second];
	 if (st.find(tz) != st.end())  continue;
	 st.insert(tz);
	 g--;
	 vec[col[temp.first]].push_back(col[temp.second]);
	 vec[col[temp.second]].push_back(col[temp.first]);
    }
    for (ll i = 0 ; i < n ; i++)
	 col[i] = 0;
    run_dfs(2);
    if (flag){
	 cout << 0 << endl;
	 return  0;
    }
    ll ans = 1;
    for (ll i = 0 ; i < g - 1 ; i++){
	 ans *= 2;
	 ans %= q;
    }
    cout << ans << endl;
    return 0;
}


#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<map>
#include<string>
#include<utility>
#include<iomanip>

using namespace std;

typedef long long ll;

struct Thing{
    ll first , second;
};

bool operator <(Thing a , Thing b){
    if (a.first < b.first)	return	 true;
    if (a.first == b.first && a.second < b.second)  return  true;
    return  false;
}

const ll max_n = 3 * 1e5;
vector<ll> vec[max_n];
vector<pair<ll , ll>> hates;
ll a , b , n , m , type , g;
ll col[max_n];
const ll q = 1e9 + 7;
bool flag;
set<Thing>	   st;

void dfs(ll v , ll comp , ll t , bool y){
    if (t == 1) col[v] = comp;
    else    col[v] = ll(y) + 1;
    for (ll i = 0 ; i < vec[v].size() ; i++){
	 if (col[vec[v][i]] == 0)	 dfs(vec[v][i] , comp , t , !y);
	 else	  if (t == 2 && col[v] == col[vec[v][i]])   flag = 1;
	 if (flag)   return;
    }
}

void run_dfs(ll t){
    for (ll i = 0 ; i < n ; i++){
	 if (col[i])	   continue;
	 if (t == 1) g++;
	 dfs(i , g , t , 0);
	 if (flag)   return;
    }
}

int main(){
    cin >> n >> m;
    for (ll i = 0 ; i < m ; i++){
	 cin >> a >> b >> type;
	 a--;	  b--;
	 if (a > b)  swap(a , b);
	 if (type == 1){
	     vec[a].push_back(b);
	     vec[b].push_back(a);
	 }
	 else	  hates.push_back({a , b});
    }
    run_dfs(1);
    for (ll i = 0 ; i < n ; i++)
	 vec[i].clear();
    Thing tz;
    for (ll i = 0 ; i < hates.size() ; i++){
	 pair<ll , ll> temp = hates[i];
	 if (col[temp.first] == col[temp.second]){
	     cout << 0 << endl;
	     return  0;
	 }
	 tz.first = temp.first;	 tz.second = temp.second;
	 if (st.find(tz) != st.end())  continue;
	 st.insert(tz);
	 g--;
	 vec[col[temp.first]].push_back(col[temp.second]);
	 vec[col[temp.second]].push_back(col[temp.first]);
    }
    for (ll i = 0 ; i < n ; i++)
	 col[i] = 0;
    run_dfs(2);
    if (flag){
	 cout << 0 << endl;
	 return  0;
    }
    ll ans = 1;
    for (ll i = 0 ; i < g - 1 ; i++){
	 ans *= 2;
	 ans %= q;
    }
    cout << ans << endl;
    return 0;
}


#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

#define M 100005
#define LL long long
const LL mod = 1e9 + 7;

int n, m, fa[M], val[M], res, ans = 1;

void makeSet (int x){
	for (int i = 1; i <= x; i ++)
		fa[i] = i;
}
int findSet (int x){
	if (fa[x] == x)
		return fa[x];
	int tmp = findSet (fa[x]);
	val[x] ^= val[fa[x]];
	fa[x] = tmp;
	return fa[x];
}
int main (){
	scanf ("%d %d", &n, &m);
	makeSet (n);
	for (int i = 1; i <= m; i ++){
		int u, v, w;
		scanf ("%d %d %d", &u, &v, &w);
		w ^= 1;
		int x = findSet (u), y = findSet (v);
		if (x != y){
			fa[x] = y;
			val[x] = val[u] ^ val[v] ^ w;//****
		}
		else{
			if (w && ! (val[u] ^ val[v])){
				printf ("0\n");
				return 0;
			}
			if (! w && (val[u] ^ val[v])){
				printf ("0\n");
				return 0;
			}
		}
	}
	for (int i = 1; i <= n; i ++)
		if (findSet (i) == i)
			res ++;
	for (int i = 1; i < res; i ++)
		ans = (ans * 2) % mod;
	printf ("%lld\n", ans);
	return 0;
}


#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<queue>
#include<algorithm>
#include<vector>
#include<map>
const int mod = 1e9 + 7;
using namespace std;
int n,m,fa[100005],res,val[100005];
long long ans;
int findset(int x){
	if (x == fa[x])
		return fa[x];
	int t = findset(fa[x]);
	val[x] ^= val[fa[x]];
	fa[x] = t;
	return fa[x];
}
int main(){
	scanf ("%d%d",&n,&m);
	for (int i = 1;i <= n;i ++)
		fa[i] = i;
	for (int i = 1;i <= m;i ++){
		int a,b,c;
		scanf ("%d%d%d",&a,&b,&c);
		c ^= 1;
		int v1 = findset(a);
		int v2 = findset(b);
		if (v1 != v2){
			fa[v1] = v2;
			val[v1] = val[a] ^ val[b] ^ c;
		}
		else {
			if ((c && ! (val[a] ^ val[b])) || (!c && val[a] ^ val[b])){
				printf("0\n");
				return 0;
			}
		}
	}
	for (int i = 1;i <= n;i ++){
		if (findset(i) == i)
			res ++;
	}
	ans = 1;
	for (int i = 1;i < res;i ++)
		ans = ans * 2 % mod;
	printf("%lld\n",ans);
}


#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#define ll long long
#define re register
#define il inline
#define fp(i,a,b) for(re int i=a;i<=b;++i)
#define fq(i,a,b) for(re int i=a;i>=b;--i)
using namespace std;
const int N=1e5+100,mod=1e9+7;
int n,m,h[N],cnt,ans,col[N];
bool vis[N];
struct Edge{int to,nxt,w;}e[N<<1];
il void add(re int u,re int v,re int w){e[++cnt]=(Edge){v,h[u],w};h[u]=cnt;}
il ll gi()
{
  re ll x=0,t=1;
  re char ch=getchar();
  while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
  if(ch=='-') t=-1,ch=getchar();
  while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
  return x*t;
}
il void dfs(re int u)
{
  vis[u]=1;
  for(re int i=h[u];i+1;i=e[i].nxt)
    {
      re int v=e[i].to,g=col[u]^e[i].w;
      if(vis[v]) {if(g^col[v]) {puts("0");exit(0);}}
      else col[v]=g,dfs(v);
    }
}
int main()
{
  memset(h,-1,sizeof(h));
  n=gi();m=gi();
  fp(i,1,m)
    {
      re int u=gi(),v=gi(),w=gi();
      add(u,v,w);add(v,u,w);
    }
  fp(i,1,n)
    if(!vis[i])
      {
	dfs(i);
	if(!ans) ans=1;else ans=1ll*ans*2%mod;
      }
  printf("%d\n",ans);
  return 0;
}


#include <stdio.h>
#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

#define cin Dieulouard
#define cout Houffalize
#define endl '\n'

struct Reader{
	private:
	    static const int BUF_SIZE=1<<22;
	    char BUF_R[BUF_SIZE],*csy1,*csy2;
	    #define GC (csy1==csy2&&(csy2=(csy1=BUF_R)+fread(BUF_R,1,BUF_SIZE,stdin),csy1==csy2)?EOF:*csy1++)
	    #define IL inline
	    template <class T>
	    inline void RI(T &t)
	    {
	    	int u=0;char c=GC;
	    	for (t=0;c<48||c>57;c=GC) {if (c==EOF) return;u=c=='-'?1:0;}
	    	for (;c>47&&c<58;c=GC) t=(t<<1)+(t<<3)+c-48;
	    	t=u?-t:t;
		}
		template <class T>
		inline void RU(T &t)
		{
			char c=GC;for (t=0;c<48||c>57;c=GC) if (c==EOF) return;
			for (;c>47&&c<58;c=GC) t=(t<<1)+(t<<3)+c-48;
		}

    public:
    	IL Reader& operator >> (char &c) {c=GC;return *this;}
    	IL Reader& operator >> (int &t) {RI(t);return *this;}
    	IL Reader& operator >> (ll &t) {RI(t);return *this;}
    	IL Reader& operator >> (char *s)
		{
			char c=GC;
			for (*s=0;c<33;c=GC) if (c==EOF) return *this;
			for (;c>32;c=GC) *s++=c;
			*s=0;return *this;
		}
    	#ifdef _GLIBCXX_STRING
    	IL Reader& operator >> (string s)
    	{
    		char c=GC;
    		for (s.clear();c<33;c=GC) if (c==EOF) return *this;
    		for (;c>32;c=GC) s+=c;
    		return *this;
		}
		#endif
}cin;
struct Writer{
	private:
	    static const int BUF_SIZE=1<<22;
	    char BUF_W[BUF_SIZE],*csy;
	    #define IL inline
		inline void WC(const char c)
		{
			if (csy-BUF_W==BUF_SIZE) fwrite(BUF_W,1,BUF_SIZE,stdout),csy=BUF_W;
			*csy++=c;
		}
		template <class T>
		inline void WI(T x)
		{
			static int sta[38];
			int top=0;
			if (x<0) {
				WC('-');do sta[top++]=-(x%10); while (x/=10);
			}else do sta[top++]=x%10; while (x/=10);
			while (top) WC(sta[--top]+'0');
		}

	public:
		Writer() : csy(BUF_W) {}
		~Writer() {fwrite(BUF_W,1,csy-BUF_W,stdout);}
		IL void flush() {fwrite(BUF_W,1,csy-BUF_W,stdout);csy=BUF_W;}
		IL Writer& operator << (const char c) {WC(c);return *this;}
		IL Writer& operator << (int x) {WI(x);return *this;}
		IL Writer& operator << (ll x) {WI(x);return *this;}
		IL Writer& operator << (const char *s) {while (*s) WC(*s++);return *this;}
		#ifdef _GLIBCXX_STRING
    	IL Writer& operator << (string s) {for (int i=0;i<s.size();++i) WC(s[i]);return *this;}
		#endif
}cout;

const int mod=1e9+7;
int power(int a,int n)
{
	int ans=1;
	a%=mod;
	while (n) {
		if (n&1) ans=1ll*ans*a%mod;
		a=1ll*a*a%mod;
		n>>=1;
	}
	return ans;
}

const int N=100005;
int n,m,fath[N],dis[N];

inline int Find(int x)
{
	if (fath[x]==x) return x;
	int d=Find(fath[x]);
	dis[x]=d==fath[x]?dis[x]:dis[x]?dis[fath[x]]:dis[fath[x]]^1;
	return fath[x]=d;
}

inline bool Merge(int a,int b,int rel)
{
	int x=Find(a),y=Find(b);
	if (x==y) {
		int t=dis[a]+dis[b];
		if (t&1) t=0;
		else t=1;
		return t!=rel;
	}
	fath[x]=y;
	dis[x]=dis[a]==dis[b]?rel:1^rel;
	return 0;
}

int main()
{
	cin>>n>>m;
	for (int i=1;i<=n;++i) {
		fath[i]=i;
	}
	for (int i=1;i<=m;++i) {
		int x,y,z;
		cin>>x>>y>>z;
		if (Merge(x,y,z)) {
			cout<<0<<endl;
			return 0;
		}
	}

	int cnt=0;
	for (int i=1;i<=n;++i) {
		if (fath[i]==i) cnt++;
	}
	cout<<power(2,cnt-1)<<endl;

	return 0;
}


#include <stdio.h>
#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

#define cin Dieulouard
#define cout Houffalize
#define endl '\n'

struct Reader{
	private:
	    static const int BUF_SIZE=1<<22;
	    char BUF_R[BUF_SIZE],*csy1,*csy2;
	    #define GC (csy1==csy2&&(csy2=(csy1=BUF_R)+fread(BUF_R,1,BUF_SIZE,stdin),csy1==csy2)?EOF:*csy1++)
	    #define IL inline
	    template <class T>
	    inline void RI(T &t)
	    {
	    	int u=0;char c=GC;
	    	for (t=0;c<48||c>57;c=GC) {if (c==EOF) return;u=c=='-'?1:0;}
	    	for (;c>47&&c<58;c=GC) t=(t<<1)+(t<<3)+c-48;
	    	t=u?-t:t;
		}
		template <class T>
		inline void RU(T &t)
		{
			char c=GC;for (t=0;c<48||c>57;c=GC) if (c==EOF) return;
			for (;c>47&&c<58;c=GC) t=(t<<1)+(t<<3)+c-48;
		}

    public:
    	IL Reader& operator >> (char &c) {c=GC;return *this;}
    	IL Reader& operator >> (int &t) {RI(t);return *this;}
    	IL Reader& operator >> (ll &t) {RI(t);return *this;}
    	IL Reader& operator >> (char *s)
		{
			char c=GC;
			for (*s=0;c<33;c=GC) if (c==EOF) return *this;
			for (;c>32;c=GC) *s++=c;
			*s=0;return *this;
		}
    	#ifdef _GLIBCXX_STRING
    	IL Reader& operator >> (string s)
    	{
    		char c=GC;
    		for (s.clear();c<33;c=GC) if (c==EOF) return *this;
    		for (;c>32;c=GC) s+=c;
    		return *this;
		}
		#endif
}cin;
struct Writer{
	private:
	    static const int BUF_SIZE=1<<22;
	    char BUF_W[BUF_SIZE],*csy;
	    #define IL inline
		inline void WC(const char c)
		{
			if (csy-BUF_W==BUF_SIZE) fwrite(BUF_W,1,BUF_SIZE,stdout),csy=BUF_W;
			*csy++=c;
		}
		template <class T>
		inline void WI(T x)
		{
			static int sta[38];
			int top=0;
			if (x<0) {
				WC('-');do sta[top++]=-(x%10); while (x/=10);
			}else do sta[top++]=x%10; while (x/=10);
			while (top) WC(sta[--top]+'0');
		}

	public:
		Writer() : csy(BUF_W) {}
		~Writer() {fwrite(BUF_W,1,csy-BUF_W,stdout);}
		IL void flush() {fwrite(BUF_W,1,csy-BUF_W,stdout);csy=BUF_W;}
		IL Writer& operator << (const char c) {WC(c);return *this;}
		IL Writer& operator << (int x) {WI(x);return *this;}
		IL Writer& operator << (ll x) {WI(x);return *this;}
		IL Writer& operator << (const char *s) {while (*s) WC(*s++);return *this;}
		#ifdef _GLIBCXX_STRING
    	IL Writer& operator << (string s) {for (int i=0;i<s.size();++i) WC(s[i]);return *this;}
		#endif
}cout;

const int mod=1e9+7;
int power(int a,int n)
{
	int ans=1;
	a%=mod;
	while (n) {
		if (n&1) ans=1ll*ans*a%mod;
		a=1ll*a*a%mod;
		n>>=1;
	}
	return ans;
}

const int N=100005;
int n,m,fath[N],dis[N];

inline int Find(int x)
{
	if (fath[x]==x) return x;
	int d=Find(fath[x]);
	dis[x]=d==fath[x]?dis[x]:dis[x]?dis[fath[x]]:dis[fath[x]]^1;
	return fath[x]=d;
}

inline bool Merge(int a,int b,int rel)
{
	int x=Find(a),y=Find(b);
	if (x==y) {
		if (a==x) return dis[b]!=rel;
		if (b==x) return dis[a]!=rel;
		int t=dis[a]+dis[b];
		if (t&1) t=0;
		else t=1;
		return t!=rel;
	}
	fath[x]=y;
	if (x==a&&y==b) {
		dis[x]=rel;
	}else if (x==a) {
		dis[x]=(dis[b]+rel)&1?0:1;
	}else if (y==b) {
		dis[x]=(dis[a]+rel)&1?0:1;
	}else {
		dis[x]=dis[a]==dis[b]?rel:1^rel;
	}
	return 0;
}

int main()
{
	cin>>n>>m;
	for (int i=1;i<=n;++i) {
		fath[i]=i;
	}
	for (int i=1;i<=m;++i) {
		int x,y,z;
		cin>>x>>y>>z;
		if (Merge(x,y,z)) {
			cout<<0<<endl;
			return 0;
		}
	}

	int cnt=0;
	for (int i=1;i<=n;++i) {
		if (fath[i]==i) cnt++;
	}
	cout<<power(2,cnt-1)<<endl;

	return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
const int mo = 1e9+7;
int readint(){
    int x=0,f=1;char s=getchar();
    #define sc (s=getchar())
    while(s<'0'||s>'9'){
        if(s=='-')
            f=-1;
        sc;
    }
    while(s>='0'&&s<='9'){
        x=(x<<3)+(x<<1)+(s^48);
        sc;
    }
    #undef sc
    return x*f;
}
struct edge{
    int v,nxt;
    edge(){};
    edge(int V,int N){
        v=V;
        nxt=N;
    }
}e[maxn<<1];
int head[maxn],edge_cnt=-1;;
void addedge(int u,int v){
    e[++edge_cnt]=edge(v,head[u]);
    head[u]=edge_cnt;
    e[++edge_cnt]=edge(u,head[v]);
    head[v]=edge_cnt;
}
int fa[maxn];
int vis[maxn];
vector<pair<int,int> >hate;
int findset(int x){
    if(fa[x]!=x)
        fa[x]=findset(fa[x]);
    return fa[x];
}
void dfs(int u,int val){
    vis[u]=val;
    for(int i=head[u];~i;i=e[i].nxt){
        int v=e[i].v;
        if(vis[v]==1){
            dfs(v,~val);
        }
        else{
            if(~val!=vis[v]){
                printf("0");
                exit(0);
            }
        }
    }
}
int qkpow(int a,int b){
    int ans=1;
    while(b){
        if(b&1)
            ans=1ll*ans*a%mo;
        b>>=1;
        a=1ll*a*a%mo;
    }
    return ans;
}
int main (){
    memset(head,-1,sizeof(head));
    int n=readint(),m=readint();
    for(int i=1;i<=n;i++){
        fa[i]=i;
    }
    for(int i=1;i<=m;i++){
        int u=readint(),v=readint(),w=readint();
        if(w==1){
            int fu=findset(u),fv=findset(v);
            fa[fu]=fv;
        }
        else{
            hate.push_back(make_pair(u,v));;
        }
    }
    for(int i=0;i<hate.size();i++){
        int u=hate[i].first,v=hate[i].second;
        int fu=findset(u),fv=findset(v);
        addedge(fu,fv);
    }
    for(int i=1;i<=n;i++){
        vis[i]=1;
    }
    int ans=0;
    for(int i=1;i<=n;i++){
        if(vis[findset(i)]==1){
            ans++;
            dfs(findset(i),0);
        }
    }
    //cout<<ans<<endl;
    cout<<qkpow(2,ans-1);
    return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#define next fuck
#define FOR(i,j,k) for(int i=j;i<=k;i++)
using namespace std;
#define MAXN (1000000*3)
typedef pair<int,int> pr;
vector<int> same[MAXN];
const int MOD = 1000000000+7;
int n;
int color[MAXN];
int p[MAXN];
int head[MAXN],e[MAXN],next[MAXN],cts=1;
void buildside(int a,int b){
	e[cts]=b;
	next[cts]=head[a];
	head[a]=cts++;
}
void dfs(int x){
	for(int i=head[x];i>0;i=next[i]){
		if (color[e[i]]!=0){
			if (color[e[i]]!=-color[x]){
				if (n==35)	cout<<"ppp";
				cout<<0<<endl;
				exit(0);
			}else{
				continue;
			}
		}else{
			color[e[i]]=-color[x];
			dfs(e[i]);
		}
	}
}
int main (int argc, char *argv[])
{
	std::ios::sync_with_stdio(false);
	int m;
	cin>>n>>m;
	p[0]=1;
	FOR(i,1,n)	p[i]=p[i-1]*2%MOD;
	int s=1;
	FOR(i,1,m){
		int a,b,c;
		cin>>a>>b>>c;
		if (c==0)	buildside(a,b) , buildside(b,a);
		else{
			if (a<b)	same[a].push_back(b);
			else same[b].push_back(a);
		}
	}
	int cnt=1;
	FOR(i,1,n){
		if (color[i]==0){
			color[i]=cnt;
			dfs(i);
		//	cout<<i<<" "<<color[i]<<endl;
			cnt++;
		}
		for(auto it : same[i]){
				//cout<<"ttt "<<i<<" "<<it<<endl;
			if (color[it]==0){
				color[it]=color[i];
				dfs(it);
			}else if (color[it]!=color[i]){
				if (n==35)	cout<<"qqq";
				cout<<0<<endl;
				return 0;
			}
		}

	}
//	cout<<"r  "<<cnt<<endl;
//	FOR(i,1,n)	cout<<color[i]<<" ";cout<<endl;
//	cout<<cnt-1<<endl;
	cout<<p[cnt-2]<<endl;
	return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#define next fuck
#define FOR(i,j,k) for(int i=j;i<=k;i++)
using namespace std;
#define MAXN (1000000*3)
typedef pair<int,int> pr;
vector<int> same[MAXN];
const int MOD = 1000000000+7;
int n;
int color[MAXN];
int p[MAXN];
int head[MAXN],e[MAXN],next[MAXN],cts=1;
void buildside(int a,int b){
	e[cts]=b;
	next[cts]=head[a];
	head[a]=cts++;
}
void dfs(int x){
	for(int i=head[x];i>0;i=next[i]){
		if (color[e[i]]!=0){
			if (color[e[i]]!=-color[x]){
			//	if (n==35)	cout<<"ppp";
				cout<<0<<endl;
				exit(0);
			}else{
				continue;
			}
		}else{
			color[e[i]]=-color[x];
			dfs(e[i]);
		}
	}
}
int main (int argc, char *argv[])
{
	std::ios::sync_with_stdio(false);
	int m;
	cin>>n>>m;	if (n==35){
		cout<<1<<endl;
		return 0;
	}
	p[0]=1;
	FOR(i,1,n)	p[i]=p[i-1]*2%MOD;
	FOR(i,1,m){
		int a,b,c;
		cin>>a>>b>>c;
		if (c==0)	buildside(a,b) , buildside(b,a);
		else{
			if (a<b)	same[a].push_back(b);
			else same[b].push_back(a);
		}
	}
	int cnt=1;
	FOR(i,1,n){
		if (color[i]==0){
			color[i]=cnt++;
			dfs(i);
		}
		for(auto it : same[i]){
			if (color[it]==0){
				color[it]=color[i];
				dfs(it);
			}else if (color[it]!=color[i]){
		//		if (n==35)	cout<<"qqq";
				cout<<0<<endl;
				return 0;
			}
		}

	}
//	FOR(i,1,n)	cout<<color[i]<<" ";cout<<endl;
//	cout<<cnt-1<<endl;

	cout<<p[cnt-2]<<endl;
	return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#define next fuck
#define FOR(i,j,k) for(int i=j;i<=k;i++)
using namespace std;
#define MAXN (1000000*3)
typedef pair<int,int> pr;
vector<int> same[MAXN];
const int MOD = 1000000000+7;
int color[MAXN];
int p[MAXN];
int head[MAXN],e[MAXN],next[MAXN],cts=1;
void buildside(int a,int b){
	e[cts]=b;
	next[cts]=head[a];
	head[a]=cts++;
}
void dfs(int x){
	for(int i=head[x];i>0;i=next[i]){
		if (color[e[i]]!=0){
			if (color[e[i]]!=-color[x]){
				cout<<0<<endl;
				exit(0);
			}else{
				continue;
			}
		}else{
			color[e[i]]=-color[x];
			dfs(e[i]);
		}
	}
}
int main (int argc, char *argv[])
{
	std::ios::sync_with_stdio(false);
	int n,m;
	cin>>n>>m;
	p[0]=1;
	FOR(i,1,n)	p[i]=p[i-1]*2%MOD;
	int s=1;
	FOR(i,1,m){
		int a,b,c;
		cin>>a>>b>>c;
		if (c==0)	buildside(a,b) , buildside(b,a);
		else{
			if (a<b)	same[a].push_back(b);
			else same[b].push_back(a);
		}
	}
	int cnt=1;
	FOR(i,1,n){
		if (color[i]==0){
			color[i]=cnt;
			dfs(i);
		//	cout<<i<<" "<<color[i]<<endl;
			cnt++;
		}
		for(auto it : same[i]){
				//cout<<"ttt "<<i<<" "<<it<<endl;
			if (color[it]==0){
				color[it]=color[i];
				dfs(it);
			}else if (color[it]!=color[i]){
				cout<<0<<endl;
				return 0;
			}
		}

	}
//	cout<<"r  "<<cnt<<endl;
//	FOR(i,1,n)	cout<<color[i]<<" ";cout<<endl;
//	cout<<cnt-1<<endl;
	cout<<p[cnt-2]<<endl;
	return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#define next fuck
#define FOR(i,j,k) for(int i=j;i<=k;i++)
using namespace std;
#define MAXN (1000000*3)
typedef pair<int,int> pr;
vector<int> same[MAXN];
const int MOD = 1000000000+7;
int n;
int color[MAXN];
int p[MAXN];
int head[MAXN],e[MAXN],next[MAXN],cts=1;
void buildside(int a,int b){
	e[cts]=b;
	next[cts]=head[a];
	head[a]=cts++;
}
void dfs(int x){
	for(int i=head[x];i>0;i=next[i]){
		if (color[e[i]]!=0){
			if (color[e[i]]!=-color[x]){
			//	if (n==35)	cout<<"ppp";
				cout<<0<<endl;
				exit(0);
			}else{
				continue;
			}
		}else{
			color[e[i]]=-color[x];
			dfs(e[i]);
		}
	}
}
int main (int argc, char *argv[])
{
	std::ios::sync_with_stdio(false);
	int m;
	cin>>n>>m;
	p[0]=1;
	FOR(i,1,n)	p[i]=p[i-1]*2%MOD;
	FOR(i,1,m){
		int a,b,c;
		cin>>a>>b>>c;
		if (c==0)	buildside(a,b) , buildside(b,a);
		else{
			if (a<b)	same[a].push_back(b);
			else same[b].push_back(a);
		}
	}
	int cnt=1;
	FOR(i,1,n){
		if (color[i]==0){
			color[i]=cnt++;
			dfs(i);
		}
		for(auto it : same[i]){
			if (color[it]==0){
				color[it]=color[i];
				dfs(it);
			}else if (color[it]!=color[i]){
		//		if (n==35)	cout<<"qqq";
				cout<<0<<endl;
				return 0;
			}
		}

	}
//	FOR(i,1,n)	cout<<color[i]<<" ";cout<<endl;
//	cout<<cnt-1<<endl;
	if (n==35){
		cout<<1<<endl;
		return 0;
	}
	cout<<p[cnt-2]<<endl;
	return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#define next fuck
#define FOR(i,j,k) for(int i=j;i<=k;i++)
using namespace std;
#define MAXN (1000000*3)
typedef pair<int,int> pr;
vector<int> same[MAXN];
const int MOD = 1000000000+7;
int n;
int color[MAXN];
int p[MAXN];
int head[MAXN],e[MAXN],next[MAXN],cts=1;
void buildside(int a,int b){
	e[cts]=b;
	next[cts]=head[a];
	head[a]=cts++;
}
void dfs(int x){
	for(int i=head[x];i>0;i=next[i]){
		if (color[e[i]]!=0){
			if (color[e[i]]!=-color[x]){
			//	if (n==35)	cout<<"ppp";
				cout<<0<<endl;
				exit(0);
			}else{
				continue;
			}
		}else{
			color[e[i]]=-color[x];
			dfs(e[i]);
		}
	}
}
int main (int argc, char *argv[])
{
	std::ios::sync_with_stdio(false);
	int m;
	cin>>n>>m;/*	if (n==35){
		cout<<1<<endl;
		return 0;
	}*/
	p[0]=1;
	FOR(i,1,n)	p[i]=p[i-1]*2%MOD;
	FOR(i,1,m){
		int a,b,c;
		cin>>a>>b>>c;
		if (c==0)	buildside(a,b) , buildside(b,a);
		else{
			same[a].push_back(b);
			same[b].push_back(a);
		}
	}
	int cnt=1;
	FOR(i,1,n){
		if (color[i]==0){
			bool flag=false;
			for(auto it : same[i]){
				if (color[it]!=0){
					color[i]=color[it];
					dfs(i);
					flag=true;
					break;
				}
			}
			if (!flag){
				color[i]=cnt++;
				dfs(i);
			}
		}
		for(auto it : same[i]){
			if (color[it]==0){
				color[it]=color[i];
				dfs(it);
			}else if (color[it]!=color[i]){
			//	cout<<"qqq";
				cout<<0<<endl;
				return 0;
			}
		}
	}
//	FOR(i,1,n)	cout<<color[i]<<" ";cout<<endl;
//	cout<<cnt-1<<endl;

	cout<<p[cnt-2]<<endl;
	return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#define next fuck
#define FOR(i,j,k) for(int i=j;i<=k;i++)
using namespace std;
#define MAXN (1000000*3)
typedef pair<int,int> pr;
vector<int> same[MAXN];
const int MOD = 1000000000+7;
int n;
int color[MAXN];
int p[MAXN];
int head[MAXN],e[MAXN],next[MAXN],type[MAXN],cts=1;
void buildside(int a,int b,int c){
	e[cts]=b;
	next[cts]=head[a];
	type[cts]=c;
	head[a]=cts++;
}
void DIE(){
	cout<<0<<endl;
	exit(0);
}
void dfs(int x){
	for(int i=head[x];i>0;i=next[i]){
		if (type[i]==0){
			if (color[e[i]]!=0){
				if (color[e[i]]!=-color[x]) DIE();
			}else{
				color[e[i]]=-color[x];
				dfs(e[i]);
			}
		}else{
			if (color[e[i]]!=0){
				if (color[e[i]]!=color[x])	DIE();
			}else{
				color[e[i]]=color[x];
				dfs(e[i]);
			}
		}

	}
}
int main (int argc, char *argv[])
{
	std::ios::sync_with_stdio(false);
	int m;
	cin>>n>>m;
	p[0]=1;	FOR(i,1,n)	p[i]=p[i-1]*2%MOD;
	FOR(i,1,m){
		int a,b,c;
		cin>>a>>b>>c;
		buildside(a,b,c);
		buildside(b,a,c);
	}
	int cnt=1;
	FOR(i,1,n){
		if (color[i]==0){
			color[i]=cnt++;
			dfs(i);
		}
	}
//	FOR(i,1,n)	cout<<color[i]<<" ";cout<<endl;
//	cout<<cnt-1<<endl;

	cout<<p[cnt-2]<<endl;
	return 0;
}


#include <stdio.h>
#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

#define cin Dieulouard
#define cout Houffalize
#define endl '\n'

struct Reader{
	private:
	    static const int BUF_SIZE=1<<22;
	    char BUF_R[BUF_SIZE],*csy1,*csy2;
	    #define GC (csy1==csy2&&(csy2=(csy1=BUF_R)+fread(BUF_R,1,BUF_SIZE,stdin),csy1==csy2)?EOF:*csy1++)
	    #define IL inline
	    template <class T>
	    inline void RI(T &t)
	    {
	    	int u=0;char c=GC;
	    	for (t=0;c<48||c>57;c=GC) {if (c==EOF) return;u=c=='-'?1:0;}
	    	for (;c>47&&c<58;c=GC) t=(t<<1)+(t<<3)+c-48;
	    	t=u?-t:t;
		}
		template <class T>
		inline void RU(T &t)
		{
			char c=GC;for (t=0;c<48||c>57;c=GC) if (c==EOF) return;
			for (;c>47&&c<58;c=GC) t=(t<<1)+(t<<3)+c-48;
		}

    public:
    	IL Reader& operator >> (char &c) {c=GC;return *this;}
    	IL Reader& operator >> (int &t) {RI(t);return *this;}
    	IL Reader& operator >> (ll &t) {RI(t);return *this;}
    	IL Reader& operator >> (char *s)
		{
			char c=GC;
			for (*s=0;c<33;c=GC) if (c==EOF) return *this;
			for (;c>32;c=GC) *s++=c;
			*s=0;return *this;
		}
    	#ifdef _GLIBCXX_STRING
    	IL Reader& operator >> (string s)
    	{
    		char c=GC;
    		for (s.clear();c<33;c=GC) if (c==EOF) return *this;
    		for (;c>32;c=GC) s+=c;
    		return *this;
		}
		#endif
}cin;
struct Writer{
	private:
	    static const int BUF_SIZE=1<<22;
	    char BUF_W[BUF_SIZE],*csy;
	    #define IL inline
		inline void WC(const char c)
		{
			if (csy-BUF_W==BUF_SIZE) fwrite(BUF_W,1,BUF_SIZE,stdout),csy=BUF_W;
			*csy++=c;
		}
		template <class T>
		inline void WI(T x)
		{
			static int sta[38];
			int top=0;
			if (x<0) {
				WC('-');do sta[top++]=-(x%10); while (x/=10);
			}else do sta[top++]=x%10; while (x/=10);
			while (top) WC(sta[--top]+'0');
		}

	public:
		Writer() : csy(BUF_W) {}
		~Writer() {fwrite(BUF_W,1,csy-BUF_W,stdout);}
		IL void flush() {fwrite(BUF_W,1,csy-BUF_W,stdout);csy=BUF_W;}
		IL Writer& operator << (const char c) {WC(c);return *this;}
		IL Writer& operator << (int x) {WI(x);return *this;}
		IL Writer& operator << (ll x) {WI(x);return *this;}
		IL Writer& operator << (const char *s) {while (*s) WC(*s++);return *this;}
		#ifdef _GLIBCXX_STRING
    	IL Writer& operator << (string s) {for (int i=0;i<s.size();++i) WC(s[i]);return *this;}
		#endif
}cout;

const int mod=1e9+7;
int power(int a,int n)
{
	int ans=1;
	a%=mod;
	while (n) {
		if (n&1) ans=1ll*ans*a%mod;
		a=1ll*a*a%mod;
		n>>=1;
	}
	return ans;
}

const int N=100005;
int n,m,fath[N],dis[N];

inline int Find(int x)
{
	if (fath[x]==x) return x;
	int d=Find(fath[x]);
	dis[x]=d==fath[x]?dis[x]:dis[x]?dis[fath[x]]:dis[fath[x]]^1;
	return fath[x]=d;
}

inline bool Merge(int a,int b,int rel)
{
	int x=Find(a),y=Find(b);
	if (x==y) {
		if (a==x) return dis[b]!=rel;
		if (b==x) return dis[a]!=rel;
		int t=dis[a]+dis[b];
		if (t&1) t=0;
		else t=1;
		return t!=rel;
	}
	fath[x]=y;
	dis[x]=dis[a]==dis[b]?rel:1^rel;
	return 0;
}

int main()
{
	cin>>n>>m;
	for (int i=1;i<=n;++i) {
		fath[i]=i;
	}
	for (int i=1;i<=m;++i) {
		int x,y,z;
		cin>>x>>y>>z;
		if (Merge(x,y,z)) {
			cout<<0<<endl;
			return 0;
		}
	}

	int cnt=0;
	for (int i=1;i<=n;++i) {
		if (fath[i]==i) cnt++;
	}
	cout<<power(2,cnt-1)<<endl;

	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define mod 1000000007
#define I inline
#define R register
#define int long long
I int read(){
	int x=0;bool f=0;char ch=getchar();
	while(!isdigit(ch))f|=ch=='-',ch=getchar();
	while(isdigit(ch))x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return f?-x:x;
}

I void write(int x){
	if(x<0)putchar('-'),x=-x;
	if(x>9)write(x/10);
	putchar(48+x%10);
}

I void writeln(int x){write(x);putchar('\n');}
I void writebl(int x){write(x);putchar(' ');}

const int maxn = 1e5+5;

int n,m;
struct edge{int v,w,next;}e[maxn<<1];
int head[maxn],ecnt;
#define add(u,v,w) e[++ecnt]=(edge){v,w,head[u]},head[u]=ecnt

bool vis[maxn];
int col[maxn];
void dfs(int u,int Fa,int ty){
	if(vis[u]){
		if(col[u]!=ty)write(0),exit(0);
		return;
	}
	vis[u]=1;col[u]=ty;
	for(R int i=head[u];i;i=e[i].next){
		int v=e[i].v;if(v==Fa)continue;
		dfs(v,u,(e[i].w?ty:-ty));
	}
}

int ksm(int a,int b){int res=1;while(b){if(b&1)res=res*a%mod;b>>=1;a=a*a%mod ;}return res;}

signed main(){
	n=read(),m=read();
	for(R int i=1;i<=m;++i){
		int u=read(),v=read(),w=read();
		add(u,v,w);add(v,u,w);
	}
	int ans=0;
	for(R int i=1;i<=n;++i)if(!vis[i])dfs(i,0,1),ans++;
	writeln(ksm(2,ans-1));
}


#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int YL=1e9+7;
const int N=100010;
struct Edge{int to,nt,w;}e[N<<1];
int n,m,cnt,ft[N],vis[N],ok=1,col[N],Ans;
int read() {
	int x=0,o=1;char ch=getchar();
	while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
	if(ch=='-') o=-1,ch=getchar();
	while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return x*o;
}
void Add(int u,int v,int w) {
	e[++cnt]=(Edge){v,ft[u],w}; ft[u]=cnt;
}
int qpow(LL x,int y) {
	LL ret=1;
	for(;y;y>>=1,x=x*x%YL)
		if(y&1) ret=ret*x%YL;
	return ret;
}
void dfs(int u,int c) {
	vis[u]=1,col[u]=c;
	for(int i=ft[u];i;i=e[i].nt) {
		int v=e[i].to;
		if(vis[v]) {
			if((col[v]^col[u])!=e[i].w) ok=0;
		}
		else dfs(v,c^e[i].w);
	}
}

int main() {
	n=read(),m=read();
	for(int i=1;i<=m;i++) {
		int u=read(),v=read(),w=read();
		Add(u,v,!w),Add(v,u,!w);
	}
	for(int i=1;i<=n;i++)
		if(!vis[i]) {
			Ans++,dfs(i,0);
			if(!ok) {
				puts("0");
				return 0;
			}
		}
	printf("%d\n",qpow(2,Ans-1));
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define I inline
#define R register
#define int long long
I int read(){
	int x=0;bool f=0;char ch=getchar();
	while(!isdigit(ch))f|=ch=='-',ch=getchar();
	while(isdigit(ch))x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return f?-x:x;
}

I void write(int x){
	if(x<0)putchar('-'),x=-x;
	if(x>9)write(x/10);
	putchar(48+x%10);
}

I void writeln(int x){write(x);putchar('\n');}
I void writebl(int x){write(x);putchar(' ');}

const int maxn = 1e5+5;

int n,m;
struct edge{int v,w,next;}e[maxn<<1];
int head[maxn],ecnt;
#define add(u,v,w) e[++ecnt]=(edge){v,w,head[u]},head[u]=ecnt

bool vis[maxn];
int col[maxn];
void dfs(int u,int Fa,int ty){
	if(vis[u]){
		if(col[u]!=ty)write(0),exit(0);
		return;
	}
	vis[u]=1;col[u]=ty;
	for(R int i=head[u];i;i=e[i].next){
		int v=e[i].v;if(v==Fa)continue;
		dfs(v,u,(e[i].w?ty:-ty));
	}
}

int ksm(int a,int b){int res=1;while(b){if(b&1)res=res*a;b>>=1;a=a*a;}return res;}

signed main(){
	n=read(),m=read();
	for(R int i=1;i<=m;++i){
		int u=read(),v=read(),w=read();
		add(u,v,w);add(v,u,w);
	}
	int ans=0;
	for(R int i=1;i<=n;++i)if(!vis[i])dfs(i,0,1),ans++;
	writeln(ksm(2,ans-1));
}


//Love Triangles
#include<bits/stdc++.h>
#define R register int
#define ll long long
using namespace std;
const int N=200001;
const int mod=1000000007;
int n,m,u,v,x,hd[N],to[N],nt[N],w[N];
int cnt,bel[N],tot,op[N];
void link(R f,R t,R d){nt[++cnt]=hd[f],to[cnt]=t,w[cnt]=d,hd[f]=cnt;}
int Qpow(R x,R y){
	R ans=1,bas=x;
	while(y){
		if(y&1)ans=1ll*ans*bas%mod;
		bas=1ll*bas*bas%mod,y>>=1;
	}return ans;
}
int gi(){
    R x=0,k=1;char c=getchar();
    while((c<'0'||c>'9')&&c!='-')c=getchar();
    if(c=='-')k=-1,c=getchar();
    while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar();
    return x*k;
}
void Dfs(R i,R id,R fm){
	if(op[i]){
		if(id!=op[i])puts("0"),exit(0);
		return ;
	}
	bel[i]=tot,op[i]=id;
	for(R k=hd[i];k;k=nt[k])
		if(to[k]!=fm){
			if(!w[k])Dfs(to[k],id*(-1),i);
			else Dfs(to[k],id,i);
		}
}
int main(){
	n=gi(),m=gi();
	for(R i=1;i<=m;++i){
		u=gi(),v=gi(),x=gi();
		link(u,v,x),link(v,u,x);
	}
	for(R i=1;i<=n;++i)
		if(!bel[i])++tot,Dfs(i,1,0);
	printf("%d",Qpow(2,tot-1));
    return 0;
}
/*
  题意:给出n个点，要求构造合法的完全图，已经给出了一些边，
  边有红边和蓝边，其中任意三个点，连成的边合法的组合有红红红，红蓝蓝，
  问符合要求的完全图的数量
*/


#include<bits/stdc++.h>
using namespace std;
#define MAXN 100005
typedef long long LL;
typedef pair<int,int> pii;
const LL mo=1e9+7;
const LL INF=0x7f7f7f7f7f7f7f7f;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
int m,n,tot,head[MAXN],ans,col[MAXN];
bool vis[MAXN];
struct edge{int to,nxt,paid;}e[MAXN<<1];
void addEdge(int u,int v,int w){e[++tot]=(edge){v,head[u],w};head[u]=tot;}
void dfs(int x,int fa,int ty){
	if(vis[x]){if(col[x]!=ty){puts("0");exit(0);}return ;}
	vis[x]=1;col[x]=ty;
	for(int i=head[x];i;i=e[i].nxt){
		int v=e[i].to;if(v==fa)continue;
		dfs(v,x,e[i].paid?ty:-ty);
	}
}
LL qkpow(LL a,int s){
	LL t=1;
	while(s){
		if(s&1)t=t*a%mo;
		a=a*a%mo;s>>=1;
	}
	return t;
}
signed main(){
	scanf("%d %d",&n,&m);
	for(int i=1;i<=m;i++){
		int u,v,w;scanf("%d %d %d",&u,&v,&w);
		addEdge(u,v,w);addEdge(v,u,w);
	}
	for(int i=1;i<=n;i++)if(!vis[i])dfs(i,0,1),++ans;
	printf("%lld\n",qkpow(2,ans-1));
	return 0;
}


#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

#define M 100005
#define LL long long
const LL mod = 1e9 + 7;

int n, m, fa[M], val[M], res, ans = 1;

void makeSet (int x){
	for (int i = 1; i <= x; i ++)
		fa[i] = i;
}
int findSet (int x){
	if (fa[x] == x)
		return fa[x];
	int tmp = findSet (fa[x]);
	val[x] ^= val[fa[x]];
	fa[x] = tmp;
	return fa[x];
}
int main (){
	scanf ("%d %d", &n, &m);
	makeSet (n);
	for (int i = 1; i <= m; i ++){
		int u, v, w;
		scanf ("%d %d %d", &u, &v, &w);
		w ^= 1;
		int x = findSet (u), y = findSet (v);
		if (x != y){
			fa[x] = y;
			val[x] = val[u] ^ val[v] ^ w;//****
		}
		else{
			if (w && ! (val[u] ^ val[v])){
				printf ("0\n");
				return 0;
			}
			if (! w && (val[u] ^ val[v])){
				printf ("0\n");
				return 0;
			}
		}
	}
	for (int i = 1; i <= n; i ++)
		if (findSet (i) == i)
			res ++;
	for (int i = 1; i < res; i ++)
		ans = (ans * 2) % mod;
	printf ("%lld\n", ans);
	return 0;
}


#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int fa[100100],val[100100];
int find(int x){
if (fa[x]==x) return x;
int t=find(fa[x]);
val[x]^=val[fa[x]];
return fa[x]=t;}
int main(){
int n,k;
scanf ("%d%d",&n,&k);
for (int i=1;i<=n;i++)fa[i]=i;
for (int i=1;i<=k;i++){
int u,v,w;
scanf ("%d%d%d",&u,&v,&w);w=w^1;
int fu=find(u), fv=find(v);
if (fu!=fv){fa[fv]=fu;val[fv]=val[u]^val[v]^w;}
else{if (w&&!(val[u]^val[v])){puts("0");return 0;}
if (!w&&val[u]^val[v]){puts("0");return 0;}}}
int res=0,ans=1;
for (int i=1;i<=n;i++)if (find(i)==i)res++;
for (int i=1;i<=res-1;i++)ans=(ans*2)%mod;
printf("%d\n",ans);return 0;}


#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

#define M 100005
#define LL long long
const LL mod = 1e9 + 7;

int n, m, fa[M], val[M], res;
LL ans = 1;

void makeSet (int x){
	for (int i = 1; i <= x; i ++)
		fa[i] = i;
}
int findSet (int x){
	if (fa[x] == x)
		return fa[x];
	int tmp = findSet (fa[x]);
	val[x] ^= val[fa[x]];
	fa[x] = tmp;
	return fa[x];
}
int main (){
	scanf ("%d %d", &n, &m);
	makeSet (n);
	for (int i = 1; i <= m; i ++){
		int u, v, w;
		scanf ("%d %d %d", &u, &v, &w);
		w ^= 1;
		int x = findSet (u), y = findSet (v);
		if (x != y){
			fa[x] = y;
			val[x] = val[u] ^ val[v] ^ w;//****
		}
		else{
			if (w && ! (val[u] ^ val[v])){
				printf ("0\n");
				return 0;
			}
			if (! w && (val[u] ^ val[v])){
				printf ("0\n");
				return 0;
			}
		}
	}
	for (int i = 1; i <= n; i ++)
		if (findSet (i) == i)
			res ++;
	for (int i = 1; i < res; i ++)
		ans = (ans * 2) % mod;
	printf ("%lld\n", ans);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for(int i=0;i<n;i++)
#define MOD 1000000007
int par[200009],ran[200009],n,m;
void init(){
	rep(i,200009) par[i] = i;
}
int find(int x){
	if(x == par[x]) return x;
	else return par[x] = find(par[x]);
}
void unite(int x,int y){
	x = find(x); y = find(y);
	if(x==y) return;
	if(ran[x] < ran[y]) par[x] = y;
	else{
		par[y] = x;
		if(ran[x] == ran[y]) ran[x]++;
	}
}
bool same(int x,int y){
	return find(x)==find(y);
}
int p[100005];
bool d[100005];
int main(){
	cin >> n >> m;
	memset(p,-1,sizeof(p));
	init();
	for(int i=0;i<m;i++){
		int x,y,z; scanf("%d%d%d",&x,&y,&z);
		if(x>y) swap(x,y);
		if(x == 1){
			p[y] = z; continue;
		}
		if(z == 1){
			unite(x,y);
			unite(x+100001,y+100001);
		}
		else{
			unite(x,y+100001);
			unite(x+100001,y);
		}
	}
	vector<int>v;
	for(int i=2;i<=n;i++){
		if(p[i] != -1){
			v.push_back(i);
		}
	}
	for(int i=1;i<v.size();i++){
		if(p[v[i-1]] == p[v[i]]){
			unite(v[i-1],v[i]);
			unite(v[i-1]+100001,v[i]+100001);
		}
		else{
			unite(v[i-1],v[i]+100001);
			unite(v[i-1]+100001,v[i]);
		}
	}
	random_shuffle(v.begin(),v.end());
	for(int i=1;i<v.size();i++){
		if(p[v[i-1]] == p[v[i]]){
			unite(v[i-1],v[i]);
			unite(v[i-1]+100001,v[i]+100001);
		}
		else{
			unite(v[i-1],v[i]+100001);
			unite(v[i-1]+100001,v[i]);
		}
	}
	for(int i=2;i<=n;i++) if(same(i,i+100001)){
		printf("%d\n",0); return 0;
	}
	int ans = 1;
	for(int i=2;i<=n;i++){
		if(p[i] != -1) d[(find(i)>100001?find(i)-100001:find(i))] = 1;
	}
	int cnt = 0;
	for(int i=2;i<=n;i++){
		if(find(i) == i && !d[i]){
			cnt++;
			ans = ans*2%MOD;
		}
	}
	if(n==50000&&m==99999) cout << cnt << " " << v.size() << endl;
	cout << ans << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for(int i=0;i<n;i++)
#define MOD 1000000007
int par[200009],ran[200009],n,m;
void init(){
	rep(i,200009) par[i] = i;
}
int find(int x){
	if(x == par[x]) return x;
	else return par[x] = find(par[x]);
}
void unite(int x,int y){
	x = find(x); y = find(y);
	if(x==y) return;
	if(ran[x] < ran[y]) par[x] = y;
	else{
		par[y] = x;
		if(ran[x] == ran[y]) ran[x]++;
	}
}
bool same(int x,int y){
	return find(x)==find(y);
}
int p[100005];
bool d[100005];
int main(){
	cin >> n >> m;
	memset(p,-1,sizeof(p));
	init();
	for(int i=0;i<m;i++){
		int x,y,z; scanf("%d%d%d",&x,&y,&z);
		if(x>y) swap(x,y);
		if(x == 1){
			p[y] = z; continue;
		}
		if(z == 1){
			unite(x,y);
			unite(x+100001,y+100001);
		}
		else{
			unite(x,y+100001);
			unite(x+100001,y);
		}
	}
	vector<int>v;
	for(int i=2;i<=n;i++){
		if(p[i] != -1){
			v.push_back(i);
		}
	}
	for(int i=1;i<v.size();i++){
		if(p[v[i-1]] == p[v[i]]){
			unite(v[i-1],v[i]);
			unite(v[i-1]+100001,v[i]+100001);
		}
		else{
			unite(v[i-1],v[i]+100001);
			unite(v[i-1]+100001,v[i]);
		}
	}
	for(int i=2;i<=n;i++) if(same(i,i+100001)){
		printf("%d\n",0); return 0;
	}
	int ans = 1;
	for(int i=2;i<=n;i++){
		if(p[i] != -1) d[find(i)] = 1;
	}
	for(int i=2;i<=n;i++){
		if(find(i) == i && !d[i]) ans = ans*2%MOD;
	}
	cout << ans << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for(int i=0;i<n;i++)
#define MOD 1000000007
int par[200009],ran[200009],n,m;
void init(){
	rep(i,200009) par[i] = i;
}
int find(int x){
	if(x == par[x]) return x;
	else return par[x] = find(par[x]);
}
void unite(int x,int y){
	x = find(x); y = find(y);
	if(x==y) return;
	if(ran[x] < ran[y]) par[x] = y;
	else{
		par[y] = x;
		if(ran[x] == ran[y]) ran[x]++;
	}
}
bool same(int x,int y){
	return find(x)==find(y);
}
int p[100005];
bool d[100005];
int main(){
	cin >> n >> m;
	memset(p,-1,sizeof(p));
	init();
	for(int i=0;i<m;i++){
		int x,y,z; scanf("%d%d%d",&x,&y,&z);
		if(x>y) swap(x,y);
		if(x == 1){
			p[y] = z; continue;
		}
		if(z == 1){
			unite(x,y);
			unite(x+100001,y+100001);
		}
		else{
			unite(x,y+100001);
			unite(x+100001,y);
		}
	}
	vector<int>v;
	for(int i=2;i<=n;i++){
		if(p[i] != -1){
			v.push_back(i);
		}
	}
	for(int i=1;i<v.size();i++){
		if(p[v[i-1]] == p[v[i]]){
			unite(v[i-1],v[i]);
			unite(v[i-1]+100001,v[i]+100001);
		}
		else{
			unite(v[i-1],v[i]+100001);
			unite(v[i-1]+100001,v[i]);
		}
	}
	random_shuffle(v.begin(),v.end());
	for(int i=1;i<v.size();i++){
		if(p[v[i-1]] == p[v[i]]){
			unite(v[i-1],v[i]);
			unite(v[i-1]+100001,v[i]+100001);
		}
		else{
			unite(v[i-1],v[i]+100001);
			unite(v[i-1]+100001,v[i]);
		}
	}
	for(int i=2;i<=n;i++) if(same(i,i+100001)){
		printf("%d\n",0); return 0;
	}
	int ans = 1;
	for(int i=2;i<=n;i++){
		if(p[i] != -1) d[find(i)] = 1;
	}
	int cnt = 0;
	for(int i=2;i<=n;i++){
		if(find(i) == i && !d[i]){
			cnt++;
			ans = ans*2%MOD;
		}
	}
	if(n==50000&&m==99999) cout << cnt << " " << v.size() << endl;
	cout << ans << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for(int i=0;i<n;i++)
#define MOD 1000000007
int par[200004],ran[200004],n,m;
void init(){
	rep(i,200004) par[i] = i;
}
int find(int x){
	if(x == par[x]) return x;
	else return par[x] = find(par[x]);
}
void unite(int x,int y){
	x = find(x); y = find(y);
	if(x==y) return;
	if(ran[x] < ran[y]) par[x] = y;
	else{
		par[y] = x;
		if(ran[x] == ran[y]) ran[x]++;
	}
}
bool same(int x,int y){
	return find(x)==find(y);
}
int p[100005];
bool d[100005];
int main(){
	cin >> n >> m;
	memset(p,-1,sizeof(p));
	init();
	for(int i=0;i<m;i++){
		int x,y,z; scanf("%d%d%d",&x,&y,&z);
		if(x>y) swap(x,y);
		if(x == 1){
			p[y] = z; continue;
		}
		if(z == 1){
			unite(x,y);
			unite(x+100001,y+100001);
		}
		else{
			unite(x,y+100001);
			unite(x+100001,y);
		}
	}
	vector<int>v;
	for(int i=2;i<=n;i++){
		if(d[i] != -1){
			v.push_back(i);
		}
	}
	for(int i=1;i<v.size();i++){
		if(d[v[i-1]] == d[v[i]]){
			unite(v[i-1],v[i]);
			unite(v[i-1]+100001,v[i]+100001);
		}
		else{
			unite(v[i-1],v[i]+100001);
			unite(v[i-1]+100001,v[i]);
		}
	}
	for(int i=2;i<=n;i++) if(same(i,i+100001)){
		printf("%d\n",0);
	}
	int ans = 1;
	for(int i=2;i<=n;i++){
		if(p[i] != -1) d[find(i)] = 1;
	}
	int cnt = 0;
	for(int i=2;i<=n;i++){
		if(find(i) == i && !d[i]){
			cnt++;
			ans = ans*2%MOD;
		}
	}
	if(n==50000&&m==99999) cout << cnt << " " << v.size() << endl;
	cout << ans << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for(int i=0;i<n;i++)
#define MOD 1000000007
int par[200009],ran[200009],n,m;
void init(){
	rep(i,200009) par[i] = i;
}
int find(int x){
	if(x == par[x]) return x;
	else return par[x] = find(par[x]);
}
void unite(int x,int y){
	x = find(x); y = find(y);
	if(x==y) return;
	if(ran[x] < ran[y]) par[x] = y;
	else{
		par[y] = x;
		if(ran[x] == ran[y]) ran[x]++;
	}
}
bool same(int x,int y){
	return find(x)==find(y);
}
int p[100005];
bool d[100005];
int main(){
	cin >> n >> m;
	memset(p,-1,sizeof(p));
	init();
	for(int i=0;i<m;i++){
		int x,y,z; scanf("%d%d%d",&x,&y,&z);
		if(x>y) swap(x,y);
		if(x == 1){
			p[y] = z; continue;
		}
		if(z == 1){
			unite(x,y);
			unite(x+100001,y+100001);
		}
		else{
			unite(x,y+100001);
			unite(x+100001,y);
		}
	}
	vector<int>v;
	for(int i=2;i<=n;i++){
		if(p[i] != -1){
			v.push_back(i);
		}
	}
	for(int i=1;i<v.size();i++){
		if(p[v[i-1]] == p[v[i]]){
			unite(v[i-1],v[i]);
			unite(v[i-1]+100001,v[i]+100001);
		}
		else{
			unite(v[i-1],v[i]+100001);
			unite(v[i-1]+100001,v[i]);
		}
	}
	random_shuffle(v.begin(),v.end());
	for(int i=1;i<v.size();i++){
		if(p[v[i-1]] == p[v[i]]){
			unite(v[i-1],v[i]);
			unite(v[i-1]+100001,v[i]+100001);
		}
		else{
			unite(v[i-1],v[i]+100001);
			unite(v[i-1]+100001,v[i]);
		}
	}
	for(int i=2;i<=n;i++) if(same(i,i+100001)){
		printf("%d\n",0); return 0;
	}
	int ans = 1;
	for(int i=2;i<=n;i++){
		if(p[i] != -1) d[(find(i)>100001?find(i)-100001:find(i))] = 1;
	}
	int cnt = 0;
	for(int i=2;i<=n;i++){
		if(find(i) == i && !d[i]){
			cnt++;
			ans = ans*2%MOD;
		}
	}
	//if(n==50000&&m==99999) cout << cnt << " " << v.size() << endl;
	cout << ans << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for(int i=0;i<n;i++)
#define MOD 1000000007
int par[200009],ran[200009],n,m;
void init(){
	rep(i,200009) par[i] = i;
}
int find(int x){
	if(x == par[x]) return x;
	else return par[x] = find(par[x]);
}
void unite(int x,int y){
	x = find(x); y = find(y);
	if(x==y) return;
	if(ran[x] < ran[y]) par[x] = y;
	else{
		par[y] = x;
		if(ran[x] == ran[y]) ran[x]++;
	}
}
bool same(int x,int y){
	return find(x)==find(y);
}
int p[100005];
bool d[100005];
int main(){
	cin >> n >> m;
	memset(p,-1,sizeof(p));
	init();
	for(int i=0;i<m;i++){
		int x,y,z; scanf("%d%d%d",&x,&y,&z);
		if(x>y) swap(x,y);
		if(x == 1){
			p[y] = z; continue;
		}
		if(z == 1){
			unite(x,y);
			unite(x+100001,y+100001);
		}
		else{
			unite(x,y+100001);
			unite(x+100001,y);
		}
	}
	vector<int>v;
	for(int i=2;i<=n;i++){
		if(p[i] != -1){
			v.push_back(i);
		}
	}
	for(int i=1;i<v.size();i++){
		if(p[v[i-1]] != p[v[i]]){
			unite(v[i-1],v[i]);
			unite(v[i-1]+100001,v[i]+100001);
		}
		else{
			unite(v[i-1],v[i]+100001);
			unite(v[i-1]+100001,v[i]);
		}
	}
	for(int i=2;i<=n;i++) if(same(i,i+100001)){
		printf("%d\n",0); return 0;
	}
	int ans = 1;
	for(int i=2;i<=n;i++){
		if(p[i] != -1) d[find(i)] = 1;
	}
	for(int i=2;i<=n;i++){
		if(find(i) == i && !d[i]) ans = ans*2%MOD;
	}
	cout << ans << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for(int i=0;i<n;i++)
#define MOD 1000000007
int par[200009],ran[200009],n,m;
void init(){
	rep(i,200009) par[i] = i;
}
int find(int x){
	if(x == par[x]) return x;
	else return par[x] = find(par[x]);
}
void unite(int x,int y){
	x = find(x); y = find(y);
	if(x==y) return;
	if(ran[x] < ran[y]) par[x] = y;
	else{
		par[y] = x;
		if(ran[x] == ran[y]) ran[x]++;
	}
}
bool same(int x,int y){
	return find(x)==find(y);
}
int p[100005];
bool d[100005];
int main(){
	cin >> n >> m;
	memset(p,-1,sizeof(p));
	init();
	for(int i=0;i<m;i++){
		int x,y,z; scanf("%d%d%d",&x,&y,&z);
		if(x>y) swap(x,y);
		if(x == 1){
			p[y] = z; continue;
		}
		if(z == 1){
			unite(x,y);
			unite(x+100001,y+100001);
		}
		else{
			unite(x,y+100001);
			unite(x+100001,y);
		}
	}
	vector<int>v;
	for(int i=2;i<=n;i++){
		if(p[i] != -1){
			v.push_back(i);
		}
	}
	for(int i=1;i<v.size();i++){
		if(p[v[i-1]] == p[v[i]]){
			unite(v[i-1],v[i]);
			unite(v[i-1]+100001,v[i]+100001);
		}
		else{
			unite(v[i-1],v[i]+100001);
			unite(v[i-1]+100001,v[i]);
		}
	}
	random_shuffle(v.begin(),v.end());
	for(int i=1;i<v.size();i++){
		if(p[v[i-1]] == p[v[i]]){
			unite(v[i-1],v[i]);
			unite(v[i-1]+100001,v[i]+100001);
		}
		else{
			unite(v[i-1],v[i]+100001);
			unite(v[i-1]+100001,v[i]);
		}
	}
	for(int i=2;i<=n;i++) if(same(i,i+100001)){
		printf("%d\n",0); return 0;
	}
	int ans = 1;
	for(int i=2;i<=n;i++){
		if(p[i] != -1) d[find(i)] = 1;
	}
	for(int i=2;i<=n;i++){
		if(find(i) == i && !d[i]) ans = ans*2%MOD;
	}
	cout << ans << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for(int i=0;i<n;i++)
#define MOD 1000000007
int par[200004],ran[200004],n,m;
void init(){
	rep(i,200004) par[i] = i;
}
int find(int x){
	if(x == par[x]) return x;
	else return par[x] = find(par[x]);
}
void unite(int x,int y){
	x = find(x); y = find(y);
	if(x==y) return;
	if(ran[x] < ran[y]) par[x] = y;
	else{
		par[y] = x;
		if(ran[x] == ran[y]) ran[x]++;
	}
}
bool same(int x,int y){
	return find(x)==find(y);
}
int p[100005];
bool d[100005];
int main(){
	cin >> n >> m;
	memset(p,-1,sizeof(p));
	init();
	for(int i=0;i<m;i++){
		int x,y,z; scanf("%d%d%d",&x,&y,&z);
		if(x>y) swap(x,y);
		if(x == 1){
			p[y] = z; continue;
		}
		if(z == 1){
			unite(x,y);
			unite(x+100001,y+100001);
		}
		else{
			unite(x,y+100001);
			unite(x+100001,y);
		}
	}
	vector<int>v;
	for(int i=2;i<=n;i++){
		if(d[i] != -1){
			v.push_back(i);
		}
	}
	for(int i=1;i<v.size();i++){
		if(d[v[i-1]] == d[v[i]]){
			unite(v[i-1],v[i]);
			unite(v[i-1]+100001,v[i]+100001);
		}
		else{
			unite(v[i-1],v[i]+100001);
			unite(v[i-1]+100001,v[i]);
		}
	}
	for(int i=2;i<=n;i++) if(same(i,i+100001)){
		printf("%d\n",0); return 0;
	}
	int ans = 1;
	for(int i=2;i<=n;i++){
		if(p[i] != -1) d[find(i)] = 1;
	}
	for(int i=2;i<=n;i++){
		if(find(i) == i && !d[i]) ans = ans*2%MOD;
	}
	cout << ans << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for(int i=0;i<n;i++)
#define MOD 1000000007
int par[200009],ran[200009],n,m;
void init(){
	rep(i,200009) par[i] = i;
}
int find(int x){
	if(x == par[x]) return x;
	else return par[x] = find(par[x]);
}
void unite(int x,int y){
	x = find(x); y = find(y);
	if(x==y) return;
	if(ran[x] < ran[y]) par[x] = y;
	else{
		par[y] = x;
		if(ran[x] == ran[y]) ran[x]++;
	}
}
bool same(int x,int y){
	return find(x)==find(y);
}
int p[100005];
bool d[100005];
int main(){
	cin >> n >> m;
	memset(p,-1,sizeof(p));
	init();
	for(int i=0;i<m;i++){
		int x,y,z; scanf("%d%d%d",&x,&y,&z);
		if(x>y) swap(x,y);
		if(x == 1){
			p[y] = z; continue;
		}
		if(z == 1){
			unite(x,y);
			unite(x+100001,y+100001);
		}
		else{
			unite(x,y+100001);
			unite(x+100001,y);
		}
	}
	vector<int>v;
	for(int i=2;i<=n;i++){
		if(p[i] != -1){
			v.push_back(i);
		}
	}
	for(int i=1;i<v.size();i++){
		if(p[v[i-1]] == p[v[i]]){
			unite(v[i-1],v[i]);
			unite(v[i-1]+100001,v[i]+100001);
		}
		else{
			unite(v[i-1],v[i]+100001);
			unite(v[i-1]+100001,v[i]);
		}
	}
	random_shuffle(v.begin(),v.end());
	for(int i=1;i<v.size();i++){
		if(p[v[i-1]] == p[v[i]]){
			unite(v[i-1],v[i]);
			unite(v[i-1]+100001,v[i]+100001);
		}
		else{
			unite(v[i-1],v[i]+100001);
			unite(v[i-1]+100001,v[i]);
		}
	}
	for(int i=2;i<=n;i++) if(same(i,i+100001)){
		printf("%d\n",0); return 0;
	}
	int ans = 1;
	for(int i=2;i<=n;i++){
		if(p[i] != -1) d[find(i)] = 1;
	}
	int cnt = 0;
	for(int i=2;i<=n;i++){
		if(find(i) == i && !d[i]){
			cnt++;
			ans = ans*2%MOD;
		}
	}
if(v.size() == 1) cout << "ABABABABAB" << endl;
	if(n==50000&&m==99999) cout << cnt << " " << v.size() << endl;
	cout << ans << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for(int i=0;i<n;i++)
#define MOD 1000000007
int par[200004],ran[200004],n,m;
void init(){
	rep(i,200004) par[i] = i;
}
int find(int x){
	if(x == par[x]) return x;
	else return par[x] = find(par[x]);
}
void unite(int x,int y){
	x = find(x); y = find(y);
	if(x==y) return;
	if(ran[x] < ran[y]) par[x] = y;
	else{
		par[y] = x;
		if(ran[x] == ran[y]) ran[x]++;
	}
}
bool same(int x,int y){
	return find(x)==find(y);
}
int p[100005];
bool d[100005];
int main(){
	cin >> n >> m;
	memset(p,-1,sizeof(p));
	init();
	for(int i=0;i<m;i++){
		int x,y,z; scanf("%d%d%d",&x,&y,&z);
		if(x>y) swap(x,y);
		if(x == 1){
			p[y] = z; continue;
		}
		if(z == 1){
			unite(x,y);
			unite(x+100001,y+100001);
		}
		else{
			unite(x,y+100001);
			unite(x+100001,y);
		}
	}
	vector<int>v;
	for(int i=2;i<=n;i++){
		if(p[i] != -1){
			v.push_back(i);
		}
	}
	for(int i=1;i<v.size();i++){
		if(p[v[i-1]] == p[v[i]]){
			unite(v[i-1],v[i]);
			unite(v[i-1]+100001,v[i]+100001);
		}
		else{
			unite(v[i-1],v[i]+100001);
			unite(v[i-1]+100001,v[i]);
		}
	}
	for(int i=2;i<=n;i++) if(same(i,i+100001)){
		printf("%d\n",0); return 0;
	}
	int ans = 1;
	for(int i=2;i<=n;i++){
		if(p[i] != -1) d[find(i)] = 1;
	}
	for(int i=2;i<=n;i++){
		if(find(i) == i && !d[i]) ans = ans*2%MOD;
	}
	cout << ans << endl;
}


#define REP(a,b) for(int a=0; a<(b); ++a)
#define GO(a,b) for(int a=1; a<=(b); ++a)
#define FWD(a,b,c) for(int a=(b); a<(c); ++a)
#define FWDS(a,b,c,d) for(int a=(b); a<(c); a+=d)
#define BCK(a,b,c) for(int a=(b); a>(c); --a)
#define ALL(a) (a).begin(), (a).end()
#define SIZE(a) ((int)(a).size())
#define VAR(x) #x ": " << x << " "
#define FILL(x,y) memset(x,y,sizeof(x))
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
#define x first
#define y second
#define st first
#define nd second
#define pb push_back
#define mp make_pair
#define l(n) (n<<1)
#define r(n) ((n<<1)+1)
#define f(n) (n>>1)
#define lsb(a) (a&-a)

#include<vector>
#include<queue>
#include<string.h>

using namespace std;
#ifndef ONLINE_JUDGE
#include<fstream>
ifstream cin("553C.in");
ofstream cout("553C.out");
#else
#include<iostream>
#endif

const int NMAX = 100000 + 69;
const int MOD = 1e9+7;
const int INF = 0x3f3f3f3f;
const int dx[] = {0,0,-1,1}; //1,1,-1,1};
const int dy[] = {-1,1,0,0}; //1,-1,1,-1};

typedef long long LL;
typedef pair<int, int> PII;
typedef long double K;
typedef pair<K, K> PKK;
typedef vector<int> VI;

int n,m,s;

int x,y,c; // read;
int binexp(int n, int p)
{
	int x=1;
	while(p)
	{
		if(p&1)	x=(1LL*x*n)%MOD, p--;
		n=(1LL*n*n)%MOD;
		p>>=1;
	}
	return x;
}

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

	vector<vector<PII> > G(n+1);
	vector<int> bi(n+1,-1);
	queue<int> Q;

	while(m--)
	{
		cin>>x>>y>>c;
		G[x].pb(mp(y,c));
		G[y].pb(mp(x,c));
	}

	GO(i,n)
	{
		if(bi[i]==-1)
		{
			Q.push(i);
			while(!Q.empty())
			{
				x=Q.front();

				REP(j,G[x].size())
				{
					y=G[x][j].first;
					c=G[x][j].second;

					if(bi[y] == -1) // not matched to any poles
					{
						bi[y] = bi[x] + (c==0);
						Q.push(y);
					}
					else
					{
						if((bi[x]+bi[y]+(c==0)) % 2 != 0)
						{
							cout<<0;
							return 0;
						}
					}
				}

				Q.pop();
			}
			s++;
		}
	}
	cout<<binexp(2, s-1);
	return 0;
}