#include <bits/stdc++.h>

//#pragma GCC optimize ("O3")
//#pragma GCC optimize ("Ofast")

#define F first
#define S second
#define MT make_tuple
#define PB push_back
#define LBS 20
#define MOD ((long long)1e9+7)
#define A 13
#define B 11
#define C 17
#define MAX 1000000
#define LEFT(i) (2*(i))
#define RIGHT(i) (2*(i)+1)
#define PAR(i) ((i)/2)
#define SZ(a) ((int)(a).size())

using namespace std;

typedef long long ll;
typedef double rat;
typedef long long bi;
typedef pair<ll, ll> ii;
typedef std::vector<ii> vii;
typedef std::map<ll, ll> mii;
typedef bitset<LBS> bis;
typedef std::vector<bis> vbs;

template<class T>
void in(T &a){
  for(auto &x: a)
    cin >> x;
}

template<class T>
void out(T &a){
  for(auto x: a)
    cout << x << " ";
  cout << '\n';
}

template<class T>
void err(T &a){
  for(auto x: a)
    cerr << x << " ";
  cerr << '\n';
}

struct h{
  int operator()(const ii &a)const{
    return a.F^(a.S<<1);
  }
};

int main(){
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  string t; int n; cin >> t >> n;
  std::vector<string> s(n);
  in(s);
  sort(s.begin(), s.end(), [](const string &a, const string &b){ return SZ(a)<SZ(b); });
  map<ii, ii> hs;
  std::vector<ll> ls;
  ll st=SZ(t);
  std::vector<ll> pa(st+1), pb(st+1), at(st+1), bt(st+1);
  pa[0]=pb[0]=1; at[0]=bt[0]=0;
  for(int i=0; i<st; i++){
    pa[i+1]=(pa[i]*A)%MOD;
    pb[i+1]=(pb[i]*B)%MOD;
    at[i+1]=(at[i]+(t[i]-'a'+1)*pa[i+1])%MOD;
    bt[i+1]=(bt[i]+(t[i]-'a'+1)*pb[i+1])%MOD;
  }
  // cerr << "at: "; err(at);
  // cerr << "bt: "; err(bt);
  for(int i=0; i<n; i++){
    std::vector<ll> a(SZ(s[i])+1), b(SZ(s[i])+1);
    a[0]=b[0]=0;
    if(!SZ(ls) || ls.back()!=SZ(s[i]))
      ls.PB(SZ(s[i]));
    for(int j=0; j<SZ(s[i]); j++){
      a[j+1]=(a[j]+(s[i][j]-'a'+1)*pa[j+1])%MOD;
      b[j+1]=(b[j]+(s[i][j]-'a'+1)*pb[j+1])%MOD;
    }
    // cerr << s[i]<<" "<<a<<" "<<b<<"\n";
    ii hi={(a.back()*pa[st-SZ(s[i])])%MOD,(b.back()*pb[st-SZ(s[i])])%MOD};
    if(!hs.count(hi))
      for(auto l: ls){
        if(l==SZ(s[i]))
          break;
        hs[hi].F+=hs[{(a[l]*pa[st-l])%MOD, (b[l]*pb[st-l])%MOD}].F;
        hs[hi].S+=hs[{((a.back()-a[SZ(s[i])-l]+MOD)*pa[st-SZ(s[i])])%MOD,
          ((b.back()-b[SZ(s[i])-l]+MOD)*pb[st-SZ(s[i])])%MOD}].S;
      }
    hs[hi].F++;
    hs[hi].S++;
  }
  cerr << "hs:\n"; for(auto x: hs) cerr << x.F.F<<" "<<x.F.S<<">"<<x.S.F<<" "<<x.S.S<<"\n";
  std::vector<ll> b(st), e(st+1);
  reverse(ls.begin(), ls.end());
  for(int i=0; i<st; i++){
    for(auto l: ls){
      if(i+l>st)
        continue;
      ii hi={((at[i+l]-at[i]+MOD)*pa[st-l-i])%MOD, ((bt[i+l]-bt[i]+MOD)*pb[st-i-l])%MOD};
      if(!hs.count(hi))
        continue;
      b[i]+=hs[hi].F;
      break;
    }
    for(auto l: ls){
      if(i-l<0)
        continue;
      ii hi={((at[i]-at[i-l]+MOD)*pa[st-i])%MOD, ((bt[i]-bt[i-l]+MOD)*pb[st-i])%MOD};
      if(!hs.count(hi))
        continue;
      e[i]+=hs[hi].S;
      break;
    }
  }
  err(b);
  err(e);
  ll res=0;
  for(int i=0; i<st; i++)
    res+=b[i]*e[i];
  cout << res << "\n";
}


#include <bits/stdc++.h>

//#pragma GCC optimize ("O3")
//#pragma GCC optimize ("Ofast")

#define F first
#define S second
#define MT make_tuple
#define PB push_back
#define LBS 20
#define MOD ((long long)1e9+7)
#define A 13
#define B 11
#define C 17
#define MAX 1000000
#define LEFT(i) (2*(i))
#define RIGHT(i) (2*(i)+1)
#define PAR(i) ((i)/2)
#define SZ(a) ((int)(a).size())

using namespace std;

typedef long long ll;
typedef double rat;
typedef long long bi;
typedef pair<ll, ll> ii;
typedef std::vector<ii> vii;
typedef std::map<ll, ll> mii;
typedef bitset<LBS> bis;
typedef std::vector<bis> vbs;

template<class T>
void in(T &a){
  for(auto &x: a)
    cin >> x;
}

template<class T>
void out(T &a){
  for(auto x: a)
    cout << x << " ";
  cout << '\n';
}

template<class T>
void err(T &a){
  for(auto x: a)
    cerr << x << " ";
  cerr << '\n';
}

int main(){
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  string t; int n; cin >> t >> n;
  std::vector<string> s(n);
  std::vector<char> ish(1000000, 0);
  in(s);
  sort(s.begin(), s.end(), [](const string &a, const string &b){ return SZ(a)<SZ(b); });
  while(SZ(s) && SZ(s.back())>=SZ(t))
    s.pop_back();
  n=SZ(s);
  map<ii, ii> hs;
  std::vector<ll> ls;
  ll st=SZ(t);
  std::vector<ll> pa(st+1), pb(st+1), at(st+1), bt(st+1);
  pa[0]=pb[0]=1; at[0]=bt[0]=0;
  for(int i=0; i<st; i++){
    pa[i+1]=(pa[i]*A)%MOD;
    pb[i+1]=(pb[i]*B)%MOD;
    at[i+1]=(at[i]+(t[i]-'a'+1)*pa[i+1])%MOD;
    bt[i+1]=(bt[i]+(t[i]-'a'+1)*pb[i+1])%MOD;
  }
  // cerr << "at: "; err(at);
  // cerr << "bt: "; err(bt);
  for(int i=0; i<n; i++){
    std::vector<ll> a(SZ(s[i])+1), b(SZ(s[i])+1);
    a[0]=b[0]=0;
    if(!SZ(ls) || ls.back()!=SZ(s[i]))
      ls.PB(SZ(s[i]));
    for(int j=0; j<SZ(s[i]); j++){
      a[j+1]=(a[j]+(s[i][j]-'a'+1)*pa[j+1])%MOD;
      b[j+1]=(b[j]+(s[i][j]-'a'+1)*pb[j+1])%MOD;
    }
    // cerr << s[i]<<" "<<a<<" "<<b<<"\n";
    ii hi={(a.back()*pa[st-SZ(s[i])])%MOD,(b.back()*pb[st-SZ(s[i])])%MOD};
    if(!hs.count(hi)){
      for(int k=SZ(ls)-2; k>=0; k--){
        int l=ls[k];
        ii t={(a[l]*pa[st-l])%MOD, (b[l]*pb[st-l])%MOD};
        if(hs.count(t)){
          hs[hi].F+=hs[t].F;
          break;
        }
      }
      for(int k=SZ(ls)-2; k>=0; k--){
        int l=ls[k];
        ii t={((a.back()-a[SZ(s[i])-l]+MOD)*pa[st-SZ(s[i])])%MOD,
          ((b.back()-b[SZ(s[i])-l]+MOD)*pb[st-SZ(s[i])])%MOD};
        if(hs.count(t)){
          hs[hi].S+=hs[t].S;
          break;
        }
      }
    }
    hs[hi].F++;
    hs[hi].S++;
    ish[hi.F%SZ(ish)]=1;
    // cerr << "evw\n";
  }
  // cerr << "hs:\n"; for(auto x: hs) cerr << x.F.F<<" "<<x.F.S<<">"<<x.S.F<<" "<<x.S.S<<"\n";
  std::vector<ll> b(st), e(st+1);
  reverse(ls.begin(), ls.end());
  for(int i=0; i<st; i++){
    for(auto l: ls){
      if(i+l>st)
        continue;
      ii hi={((at[i+l]-at[i]+MOD)*pa[st-l-i])%MOD, ((bt[i+l]-bt[i]+MOD)*pb[st-i-l])%MOD};
      if(!ish[hi.F%SZ(ish)] || !hs.count(hi))
        continue;
      b[i]+=hs[hi].F;
      break;
    }
    for(auto l: ls){
      if(i-l<0)
        continue;
      ii hi={((at[i]-at[i-l]+MOD)*pa[st-i])%MOD, ((bt[i]-bt[i-l]+MOD)*pb[st-i])%MOD};
      if(!ish[hi.F%SZ(ish)] || !hs.count(hi))
        continue;
      e[i]+=hs[hi].S;
      break;
    }
  }
  // err(b);
  // err(e);
  ll res=0;
  for(int i=0; i<st; i++)
    res+=b[i]*e[i];
  cout << res << "\n";
}


#include <bits/stdc++.h>

//#pragma GCC optimize ("O3")
//#pragma GCC optimize ("Ofast")

#define F first
#define S second
#define MT make_tuple
#define PB push_back
#define LBS 20
#define MOD ((long long)1e9+7)
#define A 13
#define B 11
#define C 17
#define MAX 1000000
#define LEFT(i) (2*(i))
#define RIGHT(i) (2*(i)+1)
#define PAR(i) ((i)/2)
#define SZ(a) ((int)(a).size())

using namespace std;

typedef long long ll;
typedef double rat;
typedef long long bi;
typedef pair<ll, ll> ii;
typedef std::vector<ii> vii;
typedef std::map<ll, ll> mii;
typedef bitset<LBS> bis;
typedef std::vector<bis> vbs;

template<class T>
void in(T &a){
  for(auto &x: a)
    cin >> x;
}

template<class T>
void out(T &a){
  for(auto x: a)
    cout << x << " ";
  cout << '\n';
}

template<class T>
void err(T &a){
  for(auto x: a)
    cerr << x << " ";
  cerr << '\n';
}

int main(){
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  string t; int n; cin >> t >> n;
  std::vector<string> s(n);
  std::vector<char> ish(3e6, 0);
  in(s);
  sort(s.begin(), s.end(), [](const string &a, const string &b){ return SZ(a)<SZ(b); });
  while(SZ(s) && SZ(s.back())>=SZ(t))
    s.pop_back();
  n=SZ(s);
  map<ii, ii> hs;
  std::vector<std::vector<ll> > lsb(26), lse(26);
  ll st=SZ(t);
  std::vector<ll> pa(st+1), pb(st+1), at(st+1), bt(st+1);
  pa[0]=pb[0]=1; at[0]=bt[0]=0;
  for(int i=0; i<st; i++){
    pa[i+1]=(pa[i]*A)%MOD;
    pb[i+1]=(pb[i]*B)%MOD;
    at[i+1]=(at[i]+(t[i]-'a'+1)*pa[i+1])%MOD;
    bt[i+1]=(bt[i]+(t[i]-'a'+1)*pb[i+1])%MOD;
  }
  // cerr << "at: "; err(at);
  // cerr << "bt: "; err(bt);
  for(int i=0; i<n; i++){
    std::vector<ll> a(SZ(s[i])+1), b(SZ(s[i])+1);
    a[0]=b[0]=0;
    if(!SZ(lsb[s[i][0]-'a']) || lsb[s[i][0]-'a'].back()!=SZ(s[i]))
      lsb[s[i][0]-'a'].PB(SZ(s[i]));
    if(!SZ(lse[s[i][SZ(s[i])-1]-'a']) || lse[s[i][SZ(s[i])-1]-'a'].back()!=SZ(s[i]))
      lse[s[i][SZ(s[i])-1]-'a'].PB(SZ(s[i]));
    for(int j=0; j<SZ(s[i]); j++){
      a[j+1]=(a[j]+(s[i][j]-'a'+1)*pa[j+1])%MOD;
      b[j+1]=(b[j]+(s[i][j]-'a'+1)*pb[j+1])%MOD;
    }
    // cerr << s[i]<<" "<<a<<" "<<b<<"\n";
    ii hi={(a.back()*pa[st-SZ(s[i])])%MOD,(b.back()*pb[st-SZ(s[i])])%MOD};
    if(!hs.count(hi)){
      for(int k=SZ(lsb[s[i][0]-'a'])-2; k>=0; k--){
        int l=lsb[s[i][0]-'a'][k];
        ii t={(a[l]*pa[st-l])%MOD, (b[l]*pb[st-l])%MOD};
        if(hs.count(t)){
          hs[hi].F+=hs[t].F;
          break;
        }
      }
      for(int k=SZ(lse[s[i][SZ(s[i])-1]-'a'])-2; k>=0; k--){
        int l=lse[s[i][SZ(s[i])-1]-'a'][k];
        ii t={((a.back()-a[SZ(s[i])-l]+MOD)*pa[st-SZ(s[i])])%MOD,
          ((b.back()-b[SZ(s[i])-l]+MOD)*pb[st-SZ(s[i])])%MOD};
        if(hs.count(t)){
          hs[hi].S+=hs[t].S;
          break;
        }
      }
    }
    hs[hi].F++;
    hs[hi].S++;
    ish[hi.F%SZ(ish)]=1;
    // cerr << "evw\n";
  }
  // cerr << "hs:\n"; for(auto x: hs) cerr << x.F.F<<" "<<x.F.S<<">"<<x.S.F<<" "<<x.S.S<<"\n";
  std::vector<ll> b(st), e(st+1);
  for(int i=0; i<26; i++){
    reverse(lsb[i].begin(), lsb[i].end());
    reverse(lse[i].begin(), lse[i].end());
  }
  for(int i=0; i<st; i++){
    for(auto l: lsb[t[i]-'a']){
      if(i+l>st)
        continue;
      ii hi={((at[i+l]-at[i]+MOD)*pa[st-l-i])%MOD, ((bt[i+l]-bt[i]+MOD)*pb[st-i-l])%MOD};
      if(!ish[hi.F%SZ(ish)] || !hs.count(hi))
        continue;
      b[i]+=hs[hi].F;
      break;
    }
    if(i==0)
      continue;
    for(auto l: lse[t[i-1]-'a']){
      if(i-l<0)
        continue;
      ii hi={((at[i]-at[i-l]+MOD)*pa[st-i])%MOD, ((bt[i]-bt[i-l]+MOD)*pb[st-i])%MOD};
      if(!ish[hi.F%SZ(ish)] || !hs.count(hi))
        continue;
      e[i]+=hs[hi].S;
      break;
    }
  }
  // err(b);
  // err(e);
  ll res=0;
  for(int i=0; i<st; i++)
    res+=b[i]*e[i];
  cout << res << "\n";
}


#include <bits/stdc++.h>

//#pragma GCC optimize ("O3")
//#pragma GCC optimize ("Ofast")

#define F first
#define S second
#define MT make_tuple
#define PB push_back
#define LBS 20
#define MOD ((long long)1e9+7)
#define A 13
#define B 11
#define C 17
#define MAX 1000000
#define LEFT(i) (2*(i))
#define RIGHT(i) (2*(i)+1)
#define PAR(i) ((i)/2)
#define SZ(a) ((int)(a).size())

using namespace std;

typedef long long ll;
typedef double rat;
typedef long long bi;
typedef pair<ll, ll> ii;
typedef std::vector<ii> vii;
typedef std::map<ll, ll> mii;
typedef bitset<LBS> bis;
typedef std::vector<bis> vbs;

template<class T>
void in(T &a){
  for(auto &x: a)
    cin >> x;
}

template<class T>
void out(T &a){
  for(auto x: a)
    cout << x << " ";
  cout << '\n';
}

template<class T>
void err(T &a){
  for(auto x: a)
    cerr << x << " ";
  cerr << '\n';
}

int main(){
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  string t; int n; cin >> t >> n;
  std::vector<string> s(n);
  std::vector<char> ish(1e8, 0);
  in(s);
  sort(s.begin(), s.end(), [](const string &a, const string &b){ return SZ(a)<SZ(b); });
  while(SZ(s) && SZ(s.back())>=SZ(t))
    s.pop_back();
  n=SZ(s);
  map<ii, ii> hs;
  std::vector<ll> ls;
  ll st=SZ(t);
  std::vector<ll> pa(st+1), pb(st+1), at(st+1), bt(st+1);
  pa[0]=pb[0]=1; at[0]=bt[0]=0;
  for(int i=0; i<st; i++){
    pa[i+1]=(pa[i]*A)%MOD;
    pb[i+1]=(pb[i]*B)%MOD;
    at[i+1]=(at[i]+(t[i]-'a'+1)*pa[i+1])%MOD;
    bt[i+1]=(bt[i]+(t[i]-'a'+1)*pb[i+1])%MOD;
  }
  // cerr << "at: "; err(at);
  // cerr << "bt: "; err(bt);
  for(int i=0; i<n; i++){
    std::vector<ll> a(SZ(s[i])+1), b(SZ(s[i])+1);
    a[0]=b[0]=0;
    if(!SZ(ls) || ls.back()!=SZ(s[i]))
      ls.PB(SZ(s[i]));
    for(int j=0; j<SZ(s[i]); j++){
      a[j+1]=(a[j]+(s[i][j]-'a'+1)*pa[j+1])%MOD;
      b[j+1]=(b[j]+(s[i][j]-'a'+1)*pb[j+1])%MOD;
    }
    // cerr << s[i]<<" "<<a<<" "<<b<<"\n";
    ii hi={(a.back()*pa[st-SZ(s[i])])%MOD,(b.back()*pb[st-SZ(s[i])])%MOD};
    if(!hs.count(hi)){
      for(int k=SZ(ls)-2; k>=0; k--){
        int l=ls[k];
        ii t={(a[l]*pa[st-l])%MOD, (b[l]*pb[st-l])%MOD};
        if(hs.count(t)){
          hs[hi].F+=hs[t].F;
          break;
        }
      }
      for(int k=SZ(ls)-2; k>=0; k--){
        int l=ls[k];
        ii t={((a.back()-a[SZ(s[i])-l]+MOD)*pa[st-SZ(s[i])])%MOD,
          ((b.back()-b[SZ(s[i])-l]+MOD)*pb[st-SZ(s[i])])%MOD};
        if(hs.count(t)){
          hs[hi].S+=hs[t].S;
          break;
        }
      }
    }
    hs[hi].F++;
    hs[hi].S++;
    ish[hi.F%SZ(ish)]=1;
    // cerr << "evw\n";
  }
  // cerr << "hs:\n"; for(auto x: hs) cerr << x.F.F<<" "<<x.F.S<<">"<<x.S.F<<" "<<x.S.S<<"\n";
  std::vector<ll> b(st), e(st+1);
  reverse(ls.begin(), ls.end());
  for(int i=0; i<st; i++){
    for(auto l: ls){
      if(i+l>st)
        continue;
      ii hi={((at[i+l]-at[i]+MOD)*pa[st-l-i])%MOD, ((bt[i+l]-bt[i]+MOD)*pb[st-i-l])%MOD};
      if(!ish[hi.F%SZ(ish)] || !hs.count(hi))
        continue;
      b[i]+=hs[hi].F;
      break;
    }
    for(auto l: ls){
      if(i-l<0)
        continue;
      ii hi={((at[i]-at[i-l]+MOD)*pa[st-i])%MOD, ((bt[i]-bt[i-l]+MOD)*pb[st-i])%MOD};
      if(!ish[hi.F%SZ(ish)] || !hs.count(hi))
        continue;
      e[i]+=hs[hi].S;
      break;
    }
  }
  // err(b);
  // err(e);
  ll res=0;
  for(int i=0; i<st; i++)
    res+=b[i]*e[i];
  cout << res << "\n";
}


#include <bits/stdc++.h>

//#pragma GCC optimize ("O3")
//#pragma GCC optimize ("Ofast")

#define F first
#define S second
#define MT make_tuple
#define PB push_back
#define LBS 20
#define MOD ((long long)1e9+7)
#define A 13
#define B 11
#define C 17
#define MAX 1000000
#define LEFT(i) (2*(i))
#define RIGHT(i) (2*(i)+1)
#define PAR(i) ((i)/2)
#define SZ(a) ((int)(a).size())

using namespace std;

typedef long long ll;
typedef double rat;
typedef long long bi;
typedef pair<int, int> ii;
typedef std::vector<ii> vii;
typedef std::map<ll, ll> mii;
typedef bitset<LBS> bis;
typedef std::vector<bis> vbs;

template<class T>
void in(T &a){
  for(auto &x: a)
    cin >> x;
}

template<class T>
void out(T &a){
  for(auto x: a)
    cout << x << " ";
  cout << '\n';
}

template<class T>
void err(T &a){
  for(auto x: a)
    cerr << x << " ";
  cerr << '\n';
}

struct h{
  int operator()(const ii &a)const{
    return a.F^(a.S<<1);
  }
};

int main(){
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  string t; int n; cin >> t >> n;
  std::vector<string> s(n);
  in(s);
  sort(s.begin(), s.end(), [](const string &a, const string &b){ return SZ(a)<SZ(b); });
  map<ii, ll> hs;
  std::vector<ll> ls;
  ll st=SZ(t);
  std::vector<ll> pa(st), pb(st), at(st), bt(st);
  pa[0]=pb[0]=1; at[0]=bt[0]=t[0]-'a'+1;
  for(int i=1; i<st; i++){
    pa[i]=(pa[i-1]*A)%MOD;
    pb[i]=(pb[i-1]*B)%MOD;
    at[i]=(at[i-1]+(t[i]-'a'+1)*pa[i])%MOD;
    bt[i]=(bt[i-1]+(t[i]-'a'+1)*pb[i])%MOD;
  }
  // cerr << "at: "; err(at);
  // cerr << "bt: "; err(bt);
  for(int i=0; i<n; i++){
    ll a=0, b=0;
    if(!SZ(ls) || ls.back()!=SZ(s[i]))
      ls.PB(SZ(s[i]));
    for(auto c: s[i]){
      a=(a*A+(c-'a'+1))%MOD;
      b=(b*B+(c-'a'+1))%MOD;
    }
    // cerr << s[i]<<" "<<a<<" "<<b<<"\n";
    hs[{(a*pa[st-SZ(s[i])])%MOD,(b*pb[st-SZ(s[i])])%MOD}]++;
  }
  // cerr << "hs:\n"; for(auto x: hs) cerr << x.F.F<<" "<<x.F.S<<">"<<x.S<<"\n";
  std::vector<ll> b(st), e(st+1);
  for(auto l: ls){
    ll t=hs[{(at[l-1]*pa[st-l])%MOD, (bt[l-1]*pb[st-l])%MOD}];
    b[0]+=t;
    e[l]+=t;
    for(int i=0; i+l<st; i++){
      // cerr <<((at[i+l]-at[i]+MOD)*pa[st-l-i-1])%MOD<<" "<<((bt[i+l]-bt[i]+MOD)*pb[st-i-l-1])%MOD<<"\n";
      ll t=hs[{((at[i+l]-at[i]+MOD)*pa[st-l-i-1])%MOD, ((bt[i+l]-bt[i]+MOD)*pb[st-i-l-1])%MOD}];
      // cerr << l << " "<<i << " "<<t<<"\n";
      b[i+1]+=t;
      e[i+l+1]+=t;
    }
  }
  // err(b);
  // err(e);
  ll res=0;
  for(int i=0; i<st; i++)
    res+=b[i]*e[i];
  cout << res << "\n";
}


//https://codeforces.com/gym/101741/problem/K
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
#define fore(i,a,b) for(int i=a,ggdem=b;i<ggdem;i++)
#define FIN ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define pb push_back
#define SZ(a) ((int)(a).size())
#define ALL(a) a.begin(),a.end()
#define fst first
#define snd second

const int MAXN=4e5+15;
bool vis[MAXN];
int n,m,qid,id[MAXN],res[MAXN],sz[MAXN];
ll c[MAXN],cnt[MAXN];
string s[MAXN],a;
vector<int>g[MAXN];

struct vertex {
  int next[26],go[26];
	int p,link,bad=0;
	vector<int>leaf;
	char pch;
	vertex(int p=-1,char pch=-1):p(p),link(-1),pch(pch){
    memset(next,-1,sizeof(next));
    memset(go,-1,sizeof(go));
  }
};
vector<vertex>t;
void aho_init() { // do not forget!
	t.clear();t.pb(vertex());
}
int add_string(vector<int>&s) {
	int v=0;
	for(int c:s){
    if(t[v].next[c]<0) {
			t[v].next[c]=SZ(t);
			t.pb(vertex(v,c));
		}
		v=t[v].next[c];
	}
	if(!t[v].leaf.size()){
    sz[qid]=SZ(s);
    t[v].leaf.pb(qid++);
  }
  cnt[t[v].leaf[0]]++;
	return t[v].leaf[0];
}
int go(int v,int c);
int get_link(int v){
	if(t[v].link<0){
		if(!v||!t[v].p)t[v].link=0;
		else t[v].link=go(get_link(t[v].p),t[v].pch);
	}
	return t[v].link;
}
int go(int v,int c) {
  if(t[v].go[c]<0) {
		if(t[v].next[c]>=0)t[v].go[c]=t[v].next[c];
		else t[v].go[c]=v==0?0:go(get_link(v),c);
	}
	return t[v].go[c];
}

void setup(int i) {
	if(vis[i])return;
	vis[i]=1;
	setup(get_link(i));
	for(int j:t[get_link(i)].leaf)t[i].leaf.pb(j);
}

void debug() {
  /*
	cout<<"Aho:"<<endl;
	fore(i,0,SZ(t)) {
		cout<<i<<" : "<<t[i].bad<<" "<<get_link(i)<<endl;
		for(auto it:t[i].next) {
			cout<<i<<" "<<it.fst<<"->"<<it.snd<<endl;
		}
	}
  */
	cout<<"Leafs: "<<endl;
	fore(i,0,SZ(t)) {
		cout<<i<<" : ";for(int j:t[i].leaf)cout<<j<<" ";cout<<endl;
	}
	cout<<"G: "<<endl;
	fore(i,0,qid) {
		cout<<i<<" : ";for(int j:g[i])cout<<j<<" ";cout<<endl;
	}
  cout<<"cnt:"<<endl;
  fore(i,0,qid)cout<<cnt[i]<<endl;
  cout<<"C:"<<endl;
  fore(i,0,SZ(a))cout<<i<<" : "<<c[i]<<endl;
}
int main() {FIN;
  cin>>a;
  cin>>m;
	aho_init();
	fore(i,0,m) {
		cin>>s[i];
    vector<int>v;
    for(char c:s[i])v.pb(c-'a');
		id[i]=add_string(v);
	}
	fore(i,0,SZ(t))setup(i);
	int pos=0;
	fore(i,0,SZ(a)) {
		pos=go(pos,a[i]-'a');
		for(int j:t[pos].leaf)g[j].pb(i-sz[j]+1);
	}
  fore(i,0,qid)for(int j:g[i])c[j]+=cnt[i];
  ll res=0;
  fore(i,0,qid)for(int j:g[i])res+=cnt[i]*c[j+sz[i]];
  // debug();
  cout<<res<<endl;
}


//https://codeforces.com/gym/101741/problem/K
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
#define fore(i,a,b) for(int i=a,ggdem=b;i<ggdem;i++)
#define FIN ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define pb push_back
#define SZ(a) ((int)(a).size())
#define ALL(a) a.begin(),a.end()
#define fst first
#define snd second

const int MAXN=2e5+5;
bool vis[MAXN];
int n,m,qid,id[MAXN],res[MAXN],sz[MAXN],cnt[MAXN];
ll c[2*MAXN];
string s;
vector<int>g[MAXN];

struct vertex {
  int next[26],go[26];
	int p,link,bad=0;
	vector<int>leaf;
	char pch;
	vertex(int p=-1,char pch=-1):p(p),link(-1),pch(pch){
    memset(next,-1,sizeof(next));
    memset(go,-1,sizeof(go));
  }
};
vector<vertex>t;
void aho_init() { // do not forget!
	t.clear();t.pb(vertex());
}
int add_string(string &s) {
	int v=0;
	for(char c:s){
    if(t[v].next[c-'a']<0) {
			t[v].next[c-'a']=SZ(t);
			t.pb(vertex(v,c-'a'));
		}
		v=t[v].next[c-'a'];
	}
	if(!t[v].leaf.size()){
    sz[qid]=SZ(s);
    t[v].leaf.pb(qid++);
  }
  cnt[t[v].leaf[0]]++;
	return t[v].leaf[0];
}
int go(int v,int c);
int get_link(int v){
	if(t[v].link<0){
		if(!v||!t[v].p)t[v].link=0;
		else t[v].link=go(get_link(t[v].p),t[v].pch);
	}
	return t[v].link;
}
int go(int v,int c) {
  if(t[v].go[c]<0) {
		if(t[v].next[c]>=0)t[v].go[c]=t[v].next[c];
		else t[v].go[c]=v==0?0:go(get_link(v),c);
	}
	return t[v].go[c];
}

void setup(int i) {
	if(!i || vis[i])return;
	vis[i]=1;
	setup(get_link(i));
	for(int j:t[get_link(i)].leaf)t[i].leaf.pb(j);
}

int main() {FIN;
  cin>>s>>m;
	aho_init();
	fore(i,0,m) {
    string tmp;cin>>tmp;
		id[i]=add_string(tmp);
	}
	fore(i,0,SZ(t))setup(i);
	int pos=0;
	fore(i,0,SZ(s)) {
		pos=go(pos,s[i]-'a');
		for(int j:t[pos].leaf)c[i-sz[j]+1]+=1ll*cnt[j];
	}
  ll res=0;
  pos=0;
	fore(i,0,SZ(s)) {
		pos=go(pos,s[i]-'a');
		for(int j:t[pos].leaf)res+=1ll*cnt[j]*c[i+1];
	}
  cout<<res<<endl;
}


//https://codeforces.com/gym/101741/problem/K
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
#define fore(i,a,b) for(int i=a,ggdem=b;i<ggdem;i++)
#define FIN ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define pb push_back
#define SZ(a) ((int)(a).size())
#define ALL(a) a.begin(),a.end()
#define fst first
#define snd second

const int MAXN=2e5+5;
bool vis[MAXN];
int n,m,qid,id[MAXN],res[MAXN],sz[MAXN],cnt[MAXN];
ll c[2*MAXN];
string s;
vector<int>g[MAXN];

struct vertex {
  int next[26],go[26];
	int p,link,bad=0;
	vector<int>leaf;
	char pch;
	vertex(int p=-1,char pch=-1):p(p),link(-1),pch(pch){
    memset(next,-1,sizeof(next));
    memset(go,-1,sizeof(go));
  }
};
vector<vertex>t;
void aho_init() { // do not forget!
	t.clear();t.pb(vertex());
}
int add_string(string &s) {
	int v=0;
	for(char c:s){
    if(t[v].next[c-'a']<0) {
			t[v].next[c-'a']=SZ(t);
			t.pb(vertex(v,c-'a'));
		}
		v=t[v].next[c-'a'];
	}
	if(!t[v].leaf.size()){
    sz[qid]=SZ(s);
    t[v].leaf.pb(qid++);
  }
  cnt[t[v].leaf[0]]++;
	return t[v].leaf[0];
}
int go(int v,int c);
int get_link(int v){
	if(t[v].link<0){
		if(!v||!t[v].p)t[v].link=0;
		else t[v].link=go(get_link(t[v].p),t[v].pch);
	}
	return t[v].link;
}
int go(int v,int c) {
  if(t[v].go[c]<0) {
		if(t[v].next[c]>=0)t[v].go[c]=t[v].next[c];
		else t[v].go[c]=v==0?0:go(get_link(v),c);
	}
	return t[v].go[c];
}

void setup(int i) {
	if(vis[i])return;
	vis[i]=1;
	setup(get_link(i));
	for(int j:t[get_link(i)].leaf)t[i].leaf.pb(j);
}

int main() {FIN;
  cin>>s>>m;
	aho_init();
	fore(i,0,m) {
    string tmp;cin>>tmp;
		id[i]=add_string(tmp);
	}
	fore(i,0,SZ(t))setup(i);
	int pos=0;
	fore(i,0,SZ(s)) {
		pos=go(pos,s[i]-'a');
		for(int j:t[pos].leaf)g[j].pb(i-sz[j]+1);
	}
  fore(i,0,qid)for(int j:g[i])c[j]+=1ll*cnt[i];
  ll res=0;
  fore(i,0,qid)for(int j:g[i])res+=1ll*cnt[i]*c[j+sz[i]];
  cout<<res<<endl;
}


//https://codeforces.com/gym/101741/problem/K
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
#define fore(i,a,b) for(int i=a,ggdem=b;i<ggdem;i++)
#define FIN ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define pb push_back
#define SZ(a) ((int)(a).size())
#define ALL(a) a.begin(),a.end()
#define fst first
#define snd second

const int MAXN=2e5+5;
bool vis[MAXN];
int n,m,qid,id[MAXN],res[MAXN],sz[MAXN],cnt[MAXN];
ll c[2*MAXN];
string s;
vector<int>g[MAXN];

struct vertex {
  int next[26],go[26];
	int p,link,bad=0,leaf=-1;
	char pch;
	vertex(int p=-1,char pch=-1):p(p),link(-1),pch(pch){
    memset(next,-1,sizeof(next));
    memset(go,-1,sizeof(go));
  }
};
vector<vertex>t;
void aho_init() { // do not forget!
	t.clear();t.pb(vertex());
}
int add_string(string &s) {
	int v=0;
	for(char c:s){
    if(t[v].next[c-'a']<0) {
			t[v].next[c-'a']=SZ(t);
			t.pb(vertex(v,c-'a'));
		}
		v=t[v].next[c-'a'];
	}
  if(t[v].leaf<0) {
    sz[qid]=SZ(s);
    t[v].leaf=qid++;
  }
  cnt[t[v].leaf]++;
	return t[v].leaf;
}
int go(int v,int c);
int get_link(int v){
	if(t[v].link<0){
		if(!v||!t[v].p)t[v].link=0;
		else t[v].link=go(get_link(t[v].p),t[v].pch);
	}
	return t[v].link;
}
int go(int v,int c) {
  if(t[v].go[c]<0) {
		if(t[v].next[c]>=0)t[v].go[c]=t[v].next[c];
		else t[v].go[c]=v==0?0:go(get_link(v),c);
	}
	return t[v].go[c];
}

vector<int>get_leafs(int p) {
  if(!p)return {};
  vector<int>res=get_leafs(get_link(p));
  if(t[p].leaf!=-1)res.pb(t[p].leaf);
  return res;
}

int main() {FIN;
  cin>>s>>m;
	aho_init();
	fore(i,0,m) {
    string tmp;cin>>tmp;
		id[i]=add_string(tmp);
	}
	int pos=0;
	fore(i,0,SZ(s)) {
		pos=go(pos,s[i]-'a');
    vector<int>v=get_leafs(pos);
    for(int j:v)g[j].pb(i-sz[j]+1);
	}
  fore(i,0,qid)for(int j:g[i])c[j]+=1ll*cnt[i];
  ll res=0;
  fore(i,0,qid)for(int j:g[i])res+=1ll*cnt[i]*c[j+sz[i]];
  cout<<res<<endl;
}


//https://codeforces.com/gym/101741/problem/K
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
#define fore(i,a,b) for(int i=a,ggdem=b;i<ggdem;i++)
#define FIN ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define pb push_back
#define SZ(a) ((int)(a).size())
#define ALL(a) a.begin(),a.end()
#define fst first
#define snd second

const int MAXN=4e5+15;
bool vis[MAXN];
int n,m,qid,id[MAXN],res[MAXN],sz[MAXN];
ll c[MAXN],cnt[MAXN];
string s[MAXN],a;
vector<int>g[MAXN];

struct vertex {
	map<char,int>next,go;
	int p,link,bad=0;
	vector<int>leaf;
	char pch;
	vertex(int p=-1,char pch=-1):p(p),link(-1),pch(pch){}
};
vector<vertex>t;
void aho_init() { // do not forget!
	t.clear();t.pb(vertex());
}
int add_string(string s) {
	int v=0;
	for(char c:s){
		if(!t[v].next.count(c)){
			t[v].next[c]=SZ(t);
			t.pb(vertex(v,c));
		}
		v=t[v].next[c];
	}
	if(!t[v].leaf.size()){
    sz[qid]=SZ(s);
    t[v].leaf.pb(qid++);
  }
  cnt[t[v].leaf[0]]++;
	return t[v].leaf[0];
}
int go(int v,char c);
int get_link(int v){
	if(t[v].link<0){
		if(!v||!t[v].p)t[v].link=0;
		else t[v].link=go(get_link(t[v].p),t[v].pch);
	}
	return t[v].link;
}
int go(int v,char c) {
	if(!t[v].go.count(c)){
		if(t[v].next.count(c))t[v].go[c]=t[v].next[c];
		else t[v].go[c]=v==0?0:go(get_link(v),c);
	}
	return t[v].go[c];
}

void setup(int i) {
	if(vis[i])return;
	vis[i]=1;
	setup(get_link(i));
	for(int j:t[get_link(i)].leaf)t[i].leaf.pb(j);
}

void debug() {
	cout<<"Aho:"<<endl;
	fore(i,0,SZ(t)) {
		cout<<i<<" : "<<t[i].bad<<" "<<get_link(i)<<endl;
		for(auto it:t[i].next) {
			cout<<i<<" "<<it.fst<<"->"<<it.snd<<endl;
		}
	}
	cout<<"Leafs: "<<endl;
	fore(i,0,SZ(t)) {
		cout<<i<<" : ";for(int j:t[i].leaf)cout<<j<<" ";cout<<endl;
	}
	cout<<"G: "<<endl;
	fore(i,0,qid) {
		cout<<i<<" : ";for(int j:g[i])cout<<j<<" ";cout<<endl;
	}
  cout<<"cnt:"<<endl;
  fore(i,0,qid)cout<<cnt[i]<<endl;
  cout<<"C:"<<endl;
  fore(i,0,SZ(a))cout<<i<<" : "<<c[i]<<endl;
}
int main() {FIN;
  cin>>a;
  cin>>m;
	aho_init();
	fore(i,0,m) {
		cin>>s[i];
		id[i]=add_string(s[i]);
	}
	fore(i,0,SZ(t))setup(i);
	int pos=0;
	fore(i,0,SZ(a)) {
		pos=go(pos,a[i]);
		for(int j:t[pos].leaf)g[j].pb(i-sz[j]+1);
	}
  fore(i,0,qid)for(int j:g[i])c[j]+=cnt[i];
  ll res=0;
  fore(i,0,qid)for(int j:g[i])res+=cnt[i]*c[j+sz[i]];
  // debug();
  cout<<res<<endl;
}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

const int maxn = 300000;
const ll INF = 1e18;
const int sqrtConst = 550;
const int alphabet = 26;
const ll mod = 998244353;

struct node {
    int next[alphabet], go[alphabet];
    int prev;
    int prevCh;
    int link;
    int leafs;
    int sum_leafs;
};

node nodes[maxn];
int nodes_sz;
void init() {
    nodes_sz = 1;
    for (int j=0;j<alphabet;j++) {
        nodes[0].next[j] = nodes[0].go[j] = -1;
    }
    nodes[0].link = -1;
    nodes[0].sum_leafs = -1;
    nodes[0].leafs = 0;
}

void addString(const string& s) {
    int v =0;
    for (int i=0;i<s.size();i++) {
        int c = s[i]-'a';
        if (nodes[v].next[c]==-1) {
            for (int j=0;j<alphabet;j++) {
                nodes[nodes_sz].go[j] = nodes[nodes_sz].next[j] = -1;
            }
            nodes[nodes_sz].prev = v;
            nodes[nodes_sz].prevCh = c;
            nodes[nodes_sz].link = -1;
            nodes[nodes_sz].sum_leafs = -1;
            nodes[nodes_sz].leafs = 0;
            nodes[v].next[c] = nodes_sz++;
        }
        v = nodes[v].next[c];
    }
    nodes[v].leafs++;
}

int go(int v, int c);

int link(int v) {
   if (nodes[v].link==-1) {
       if (v==0 || nodes[v].prev==0) {
           nodes[v].link = 0;
       } else {
           nodes[v].link = go(link(nodes[v].prev), nodes[v].prevCh);
       }
   }
   return nodes[v].link;
}

int go(int v, int c) {
    if (nodes[v].go[c]==-1) {
        if (nodes[v].next[c]!=-1) {
            nodes[v].go[c] = nodes[v].next[c];
        } else {
            if (v==0) {
                nodes[v].go[c] = 0;
            } else {
                nodes[v].go[c] = go(link(v), c);
            }
        }
    }
    return nodes[v].go[c];
}

int sum_leafes(int v) {
    if (nodes[v].sum_leafs==-1) {
        if (v==0) {
            nodes[v].sum_leafs = nodes[v].leafs;
        } else {
            nodes[v].sum_leafs = sum_leafes(link(v)) + nodes[v].leafs;
        }
    }
    return nodes[v].sum_leafs;
}

void solve() {
    string t;
    cin >> t;
    int n;
    cin >> n;
    vector<string> s(n);
    for (int i=0;i<n;i++) {
        cin >> s[i];
    }

    init();
    for (int i=0;i<n;i++) {
        addString(s[i]);
    }

    vector<ll> cnts_forward(t.size());
    int v = 0;
    for (int i=0;i<t.size();i++) {
        v = go(v, t[i]-'a');
        cnts_forward[i] = sum_leafes(v);
    }

    vector<ll> cnts_backward(t.size());
    reverse(t.begin(), t.end());
    for (int i=0;i<n;i++) {
        reverse(s[i].begin(), s[i].end());
    }

    init();
    for (int i=0;i<n;i++) {
        addString(s[i]);
    }

    v = 0;
    for (int i=0;i<t.size();i++) {
        v = go(v, t[i]-'a');
        cnts_backward[i] = sum_leafes(v);
    }
    ll res = 0;
    for (int i=0;i<t.size()-1;i++) {
        int pos1 = i;
        int pos2 = t.size()-2-i;
        ll cnt = cnts_forward[pos1]*cnts_backward[pos2];
        res+=cnt;
    }
    cout << res;
}
int main() {

    cin.tie(0);
    cout.tie(0);
    ios_base::sync_with_stdio(false);
    cout << setprecision(20) << fixed;
    //   freopen("input.txt","r", stdin);
    //    freopen("output.txt","w",stdout);
    //    freopen("input.txt","w",stdout);
    //    precalc();
    //    return 0;
    //    precalc();
//        int q;
//        cin >> q;
//        for (int i=0;i<q;i++)
    solve();
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

const int maxn = 200000;
const ll INF = 1e18;
const int sqrtConst = 550;
const int alphabet = 26;
const ll mod = 998244353;

struct node {
    int next[alphabet], go[alphabet];
    int prev;
    int prevCh;
    int link;
    int leafs;
    int sum_leafs;
};

node nodes[maxn];
int nodes_sz;
void init() {
    nodes_sz = 1;
    for (int j=0;j<alphabet;j++) {
        nodes[0].next[j] = nodes[0].go[j] = -1;
    }
    nodes[0].link = -1;
    nodes[0].sum_leafs = -1;
    nodes[0].leafs = 0;
}

void addString(const string& s) {
    int v =0;
    for (int i=0;i<s.size();i++) {
        int c = s[i]-'a';
        if (nodes[v].next[c]==-1) {
            for (int j=0;j<alphabet;j++) {
                nodes[nodes_sz].go[j] = nodes[nodes_sz].next[j] = -1;
            }
            nodes[nodes_sz].prev = v;
            nodes[nodes_sz].prevCh = c;
            nodes[nodes_sz].link = -1;
            nodes[nodes_sz].sum_leafs = -1;
            nodes[nodes_sz].leafs = 0;
            nodes[v].next[c] = nodes_sz++;
        }
        v = nodes[v].next[c];
    }
    nodes[v].leafs++;
}

int go(int v, int c);

int link(int v) {
   if (nodes[v].link==-1) {
       if (v==0 || nodes[v].prev==0) {
           nodes[v].link = 0;
       } else {
           nodes[v].link = go(link(nodes[v].prev), nodes[v].prevCh);
       }
   }
   return nodes[v].link;
}

int go(int v, int c) {
    if (nodes[v].go[c]==-1) {
        if (nodes[v].next[c]!=-1) {
            nodes[v].go[c] = nodes[v].next[c];
        } else {
            if (v==0) {
                nodes[v].go[c] = 0;
            } else {
                nodes[v].go[c] = go(link(v), c);
            }
        }
    }
    return nodes[v].go[c];
}

int sum_leafes(int v) {
    if (nodes[v].sum_leafs==-1) {
        if (v==0) {
            nodes[v].sum_leafs = nodes[v].leafs;
        } else {
            nodes[v].sum_leafs = sum_leafes(link(v)) + nodes[v].leafs;
        }
    }
    return nodes[v].sum_leafs;
}

void solve() {
    string t;
    cin >> t;
    int n;
    cin >> n;
    vector<string> s(n);
    for (int i=0;i<n;i++) {
        cin >> s[i];
    }

    init();
    for (int i=0;i<n;i++) {
        addString(s[i]);
    }

    vector<ll> cnts_forward(t.size());
    int v = 0;
    for (int i=0;i<t.size();i++) {
        v = go(v, t[i]-'a');
        cnts_forward[i] = sum_leafes(v);
    }

    vector<ll> cnts_backward(t.size());
    reverse(t.begin(), t.end());
    for (int i=0;i<n;i++) {
        reverse(s[i].begin(), s[i].end());
    }

    init();
    for (int i=0;i<n;i++) {
        addString(s[i]);
    }

    v = 0;
    for (int i=0;i<t.size();i++) {
        v = go(v, t[i]-'a');
        cnts_backward[i] = sum_leafes(v);
    }
    ll res = 0;
    for (int i=0;i<t.size()-1;i++) {
        int pos1 = i;
        int pos2 = t.size()-2-i;
        ll cnt = cnts_forward[pos1]*cnts_backward[pos2];
        res+=cnt;
    }
    cout << res;
}
int main() {

    cin.tie(0);
    cout.tie(0);
    ios_base::sync_with_stdio(false);
    cout << setprecision(20) << fixed;
     //  freopen("input.txt","r", stdin);
    //    freopen("output.txt","w",stdout);
    //    freopen("input.txt","w",stdout);
    //    precalc();
    //    return 0;
    //    precalc();
//        int q;
//        cin >> q;
//        for (int i=0;i<q;i++)
    solve();
    return 0;
}


#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>

using namespace std;

const int MOD = 1000000007;

int n, m;
int num[100005];
bool bad = false;
bool visited[100005];
vector<pair<int, int>> g[100005];

void rec(int node) {
    visited[node] = true;
    for (auto nextPair : g[node]) {
        if (!visited[nextPair.first]) {
            num[nextPair.first] = num[node] + (nextPair.second == 0);
            rec(nextPair.first);
        } else {
            int cnt = (num[node] + num[nextPair.first]) & 1;
            if (cnt != 1 - nextPair.second) {
                bad = true;
            }
        }
    }
}

int main() {
    scanf("%d%d", &n, &m);
    for (int i = 0; i < m; ++i) {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        --a; --b;
        g[a].push_back(make_pair(b, c));
        g[b].push_back(make_pair(a, c));
    }

    int cnt = 0;
    memset(visited, 0, sizeof(visited));
    for (int i = 0; i < n; ++i)
        if (!visited[i]) {
            ++cnt;
            num[i] = 0;
            rec(i);
        }

    if (bad) {
        printf("0\n");
        return 0;
    }
    int res = 1;
    for (int i = 0; i < cnt - 1; ++i) {
        res += res;
        if (res >= MOD) res -= MOD;
    }
    printf("%d\n", res);
    return 0;
}


#include <iostream>
#include <cstdio>
#include <string>
#include <sstream>
#include <algorithm>
#include <set>
#include <numeric>
#include <cmath>
#include <map>
#include <vector>
#include <queue>
#include <stack>
#include <cstring>
#include <queue>
#include <numeric>
#include <iomanip>
#define ll long long
using namespace std;
int n,m;
const int MAXN = 200001;
vector<int> hate[MAXN];
vector<int> love[MAXN];
int vis[MAXN];
int color[MAXN];
const int mod = 1e9+7;
void dfs(int here,int c){
    color[here] = c;
    for(int i=0;i<love[here].size();i++){
        int there = love[here][i];
        if(color[there] != -1 && color[there]!=color[here]){
            cout<<0; exit(0);
        }
        else if(color[there] == -1) dfs(there,c);
    }
    for(int i=0;i<hate[here].size();i++){
        int there = hate[here][i];
        if(color[there] != -1 && color[there] == color[here]){
            cout<<0; exit(0);
        }
        else if(color[there] == -1)dfs(there,c^1);
    }
}
int main(){
    ios::sync_with_stdio(false); cin.tie(0);
    cin>>n>>m;
    memset(color,-1,sizeof(color));
    for(int i=1;i<=m;i++){
        int a,b,c; cin>>a>>b>>c;
        if(c == 1){
            love[a].push_back(b);
            love[b].push_back(a);
        }
        else {
            hate[a].push_back(b);
            hate[b].push_back(a);
        }
    }
    int cmp = 0;
    for(int i=1;i<=n;i++){
        if(color[i] == -1){
            dfs(i,0);
            cmp++;
        }
    }
    long long ret = 1;
    for(int i=1;i<=cmp-1;i++){
        ret *= 2;
        ret %= mod;
    }
    cout<<ret;

    return 0;
}


/*cf309 div2E ����*/
//todo
//���鼯�����Ƶ� ����ͼ �ж϶���ͼ ���ݹ�ʽ���⣬�ɿ�����
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#define ll long long
#define mod 1000000007
using namespace std;
const int maxn=100010;
int m,n,cnt,fa[maxn],pos[maxn],a[maxn],b[maxn],ptr,color[maxn];//pos[fa[x]]Ϊһ�����������
bool vis[maxn];
vector<int> g[maxn];

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

void join(int x,int y)
{
    int px=find(x),py=find(y);
    if(px==py)return;
    fa[px]=py;
}

bool dfs(int x,int now)
{
    color[x]=now;
    for(int i=0;i<g[x].size();i++){
        int& y=g[x][i];
        if(color[y]){if(color[y]==now)return false;}
        else if(!dfs(y,3-now))return false;
    }
    return true;
}

void dfs2(int x)
{
    vis[x]=1;
    for(int i=0;i<g[x].size();i++){
        int& y=g[x][i];
        if(!vis[y])dfs2(y);
    }
}

ll pow(int k)
{
    if(k==0)return 1;
    if(k==1)return 2;
    ll ans=pow(k>>1);
    ans=ans*ans%mod;
    if(k%2)ans=(ans<<1)%mod;
    return ans;
}

int main()
{
    //freopen("test.in","r",stdin);
    cin>>n>>m;
    for(int i=1;i<=n;i++)fa[i]=i;
    for(int i=1;i<=m;i++){
        int x,y,c;
        scanf("%d%d%d",&x,&y,&c);
        if(c==0){
            if(find(x)==find(y)){cout<<0<<endl; return 0;}
            a[++ptr]=x; b[ptr]=y;
        }
        else join(x,y);
    }
    for(int i=1;i<=ptr;i++){
        int& x=a[i],&y=b[i];
        g[find(x)].push_back(find(y));
        g[find(y)].push_back(find(x));
    }
    //�ж϶���ͼ
    for(int i=1;i<=n;i++)
    if(!color[find(i)]){
        if(!dfs(find(i),1)){cout<<"0"<<endl; return 0;}
    }

    for(int i=1;i<=n;i++)
    if(!vis[find(i)]){cnt++; dfs2(find(i));}

    cout<<pow(cnt-1)<<endl;
    return 0;
}


/*
 * =====================================================================================
 *
 *       Filename:  309_div2_E_love_triangles.cpp
 *
 *    Description:  http://codeforces.com/contest/554/problem/E
 *
 *        Version:  1.0
 *        Created:  07/06/2015 05:50:58 PM
 *       Revision:  none
 *       Compiler:  gcc/g++
 *
 *         Author:  Marius-Constantin Melemciuc
 *          email:
 *   Organization:
 *
 * =====================================================================================
 */

#include <iostream>
#include <vector>
#include <stack>
#include <utility>
#define LARGE_NUMBER 1000000007

using namespace std;

vector<vector<pair<int, int> > > graph;

vector<bool> visited;
vector<int> visited2;

void dfs(int vertex) {
    stack<int> s;

    s.push(vertex);
    visited[vertex] = true;

    while (!s.empty()) {
        int element = s.top();
        int count = graph[element].size();
        int i;
        bool found = false;

        for (i = 0; i < count && !found; i++) {
            if (!visited[graph[element][i].first]) {
                found = true;
            }
        } /* for */

        if (found) {
            i--;
            s.push(graph[element][i].first);
            visited[graph[element][i].first] = true;
        } else {
            s.pop();
        }
    } /* while */
}

bool isBipartite(int vertex) {
    stack<int> s;

    s.push(vertex);
    visited2[vertex] = 1;

    while (!s.empty()) {
        int element = s.top();
        int count = graph[element].size();
        int i;
        bool found = false;

        for (i = 0; i < count && !found; i++) {
            if (!visited2[graph[element][i].first]) {
                found = true;
            } else {
                // if the cost is 1, they have to have the same labeling
                // in visited2
                // if the cost is 0, they have to have different labelings
                // all this because we want to stand ONLY the case with
                // 1 0 0, 1 1 1 between three vertices to be ok
                if (graph[element][i].second == 1 &&
                    visited2[graph[element][i].first] != visited2[element])
                    return false;
                if (graph[element][i].second == 0 &&
                    visited2[graph[element][i].first] == visited2[element])
                    return false;
            }
        } /* for */

        if (found) {
            i--;
            s.push(graph[element][i].first);
            // if the cost is 1, they have to have the same labeling
            // in visited2
            // if the cost is 0, they have to have different labelings
            // all this because we want to stand ONLY the case with
            // 1 0 0, 1 1 1 between three vertices
            if (graph[element][i].second == 1)
                visited2[graph[element][i].first] = visited2[element];
            else
                visited2[graph[element][i].first] = -visited2[element];
        } else {
            s.pop();
        }
    } /* while */

    return true;
}

void solve() {
    int n = graph.size();

    int i;
    for (i = 0; i < n; i++) {
        if (!visited2[i]) {
            if (!isBipartite(i)) {
                break;
            }
        }
    } /* for */

    if (i == n) { // has solution, all connected components are bipartite
        int nr_connected_components = 0;
        for (int j = 0; j < n; j++) {
            if (!visited[j]) {
                dfs(j);
                nr_connected_components++;
            }
        }

        int answer = 1;
        for (int j = 0; j < nr_connected_components - 1; j++) {
            answer = (answer * 2) % LARGE_NUMBER;
        }
        cout << answer;
    } else {
        cout << '0';
    }
}

int main() {
    int n, m;
#ifndef ONLINE_JUDGE
    freopen("lovetriangles.in", "r", stdin);
#endif

    cin >> n >> m;

    graph.resize(n);
    visited.resize(n, false);
    visited2.resize(n, 0);

    for (int i = 0; i < m; i++) {
        int x, y, z;

        cin >> x >> y >> z;

        x--; // to label nodes from 0
        y--; // to label nodes from 0
        graph[x].push_back(make_pair(y, z));
        graph[y].push_back(make_pair(x, z));
    } /* for */

    solve();

    return 0;
}


// prob554E.cpp
//
// Analysis:
// Consider a[n]
// let subset S1 of a[1..n-1] be friends of a[n]
// and subset S2 of a[1..n-1] be enemies of a[n]
// then each pair in S1 must be friends
// and each pair in S2 must be friends
// and each a[i] in S1 and a[j] in S2 must be enemies
// So once the split is done, there is only one valid configuration
// Now use the edges, we build a graph with a collection of components
// each =1 and =0 edge would add nodes to a component, with
// =1 would add a node with the same label, =0 would add a node with different
// label. If a node receives two different labels, then ans = 0
// Suppose we have C components, ans = 2^C / 2 = 2^C-1 because every component
// can be into the first or second partition, and each partition occurs twice
// due to symmetry

#include <iostream>
#include <vector>
#include <utility>
using namespace std;

const int MOD = 1e9+7;

vector<pair<int,int>> graph[100000+5];  // (neighbor, friend 1 or enemy 0)
int label[100000+5]; // 0 not seen, 1 left, 2 right
int N, M;

bool dfs(int start, int val) {
    if (label[start] != 0) {
        return label[start] == val;
    }
    label[start] = val;
    for (const auto& p : graph[start]) {
        int nb = p.first;
        int edge = p.second;
        if (edge == 0) {
            if (!dfs(nb, 3-val)) return false;
        } else {
            if (!dfs(nb, val)) return false;
        }
    }
    return true;
}

int pow2(int l) {
    int ans = 1;
    for (int i = 0; i < l; ++i) {
        ans = 1LL * ans * 2 % MOD;
    }
    return ans;
}

int main() {
    cin >> N >> M;
    for (int i = 0; i < M; ++i) {
        int a, b, c; cin >> a >> b >> c; --a; --b;
        graph[a].push_back(make_pair(b, c));
        graph[b].push_back(make_pair(a, c));
    }
    int ans = -1;
    int comp = 0;
    for (int i = 0; i < N; ++i) if (label[i] == 0) {
        comp++;
        if (!dfs(i, 1)) {
            ans = 0;
            break;
        }
    }
    if (ans < 0) ans = pow2(comp-1);

    cout << ans << endl;
}


//yalhaye yek tedadi khushe tashkil midahand va baghiya yal ha 0 hastan va chon mosallase 0 nadarim tedad khushe haye 1 2 tast hadde aksar

//In the name of Allah

#include<bits/stdc++.h>

using namespace std;

const int Maxn = 100 * 1000 + 5, Mod = 1000 * 1000 * 1000 + 7;
int n, m, num[Maxn], ans = 1;
vector<int> adj[2][Maxn];
bool flag;

void dfs(int v, int a)
{
    num[v] = a + 1;
    for(int i = 0; i < (int)adj[0][v].size(); i ++)
    {
        if(num[adj[0][v][i]] == 0)
            dfs(adj[0][v][i], (a + 1) % 2);
        else
        {
            if(num[adj[0][v][i]] == a + 1)
                flag = true;
        }
    }
    for(int i = 0; i < (int)adj[1][v].size(); i ++)
    {
        if(num[adj[1][v][i]] == 0)
            dfs(adj[1][v][i], a);
        else
        {
            if(num[adj[1][v][i]] == 1 + (a + 1) % 2)
                flag = true;
        }
    }
    return;
}

void dfsAll()
{
    bool mrk = false;
    for(int i = 0; i < n; i ++)
    {
        if(num[i] == 0)
        {
            dfs(i, 0);
            if(mrk)
                ans *= 2, ans %= Mod;
            mrk = true;
        }
    }
}

int main()
{
    scanf("%d%d", &n, &m);
    int u, v, t;
    for(int i = 0; i < m; i ++)
    {
        scanf("%d%d%d", &u, &v, &t);
        u --; v --;
        adj[t][u].push_back(v); adj[t][v].push_back(u);
    }
    dfsAll();
    if(flag)
        printf("0\n");
    else
        printf("%d\n", ans);
    return 0;
}


#include<bits/stdc++.h>

using namespace std ;

vector< int > love[100] , hate[100] , hate1[100] ;

int vertex[100] , vi[100], color[100] ;

int n , m ;

void dfs ( int ver , int c ) {

    for ( int i = 0 ; i < love[ver].size() ; i++ ){

            if( !vi[love[ver][i]] ){

                vi[love[ver][i]]  = 1;
                vertex[love[ver][i]] = c ;
                dfs( love[ver][i] , c ) ;
            }
    }

}

int construct_collapsed (  ) {

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

        for ( int j = 0 ; j < hate[i].size() ; j++ ){

           if ( vertex[i] != vertex[ hate[i][j] ] )
                {hate1[ vertex[i] ].push_back( vertex[ hate[i][j] ] ) ;}
            else{

                return 0 ;

            }

        }

    }
    return 1 ;

}

int is_bipartite ( int ver ) {

    for ( int i = 0 ; i < hate1[ver].size() ; i++ ) {

        if ( vi[ hate1[ver][i] ] ){

            return color[ hate1[ver][i] ] != color[ver] ;

        }

        color[ hate1[ver][i] ] = !color[ver] ;
        vi[ hate1[ver][i] ] = 1 ;

        if ( !is_bipartite ( hate1[ver][i] ) ){
            return 0;
        }

    }

    return 1 ;
}

int main ( ) {

    int a , b , c , i , j ;

    cin>>n>>m ;

    for (  i = 0 ; i < m ; i++ ){

        cin>>a>>b>>c;
        if ( c == 1 )
        {
            love[a].push_back(b);
            love[b].push_back(a);
        }
        else{
            hate[a].push_back(b);
            hate[b].push_back(a);

        }
    }
       /*/ cout<<"hate"<<endl;
        for (  i = 1 ; i <= n ; i++ ){

            cout<<i<<" ";

            for (  j = 0 ; j < hate[i].size() ; j++ ){

                    cout<<hate[i][j]<<" ";
            }cout<<endl;
        }cout<<endl<<endl;

    cout<<"love"<<endl;
    for (  i = 1 ; i <= n ; i++ ){

            cout<<i<<" ";

            for (  j = 0 ; j < love[i].size() ; j++ ){

                    cout<<love[i][j]<<" ";
            }
    }cout<<endl<<endl;*/

    memset( vi , 0 , sizeof vi ) ;

    c = 0 ;

    for (  i = 1 ; i <= n ; i++ ){

        if ( !vi[i] ){

            vi[i] = 1;
            vertex[i] = ++c ;
            dfs( i , c ) ;
        }
    }
    //cout<<c<<endl;

     if ( !construct_collapsed (  ) ) {

        cout<<"0"<<endl;

     }
     else{

         int coun = 0;

         memset( vi , 0 , sizeof vi ) ;

        for (  i = 1 ;i <= c ; i++ ){

           if(!vi[i] ){

                vi[i] = 1 ;
                color[i] = 1 ;

                if (  !is_bipartite ( i ) ){
                       // cout<<i<<endl;
                    break;
                }

                coun++;
           }

        }

        if( i != c+1 ){
             cout<<"0"<<endl;
        }
        else{
            cout<<pow( 2 , coun -1 ) ;
        }

     }

    return 0;

}


#include<bits/stdc++.h>

using namespace std ;

vector< int > love[100001] , hate[100001] , hate1[100001] ;

int vertex[100001] , vi[100001], color[100001] ;

int n , m ;

void dfs ( int ver , int c ) {

    for ( int i = 0 ; i < love[ver].size() ; i++ ){

            if( !vi[love[ver][i]] ){

                vi[love[ver][i]]  = 1;
                vertex[love[ver][i]] = c ;
                dfs( love[ver][i] , c ) ;
            }
    }

}

int construct_collapsed (  ) {

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

        for ( int j = 0 ; j < hate[i].size() ; j++ ){

           if ( vertex[i] != vertex[ hate[i][j] ] )
                {hate1[ vertex[i] ].push_back( vertex[ hate[i][j] ] ) ;}
            else{

                return 0 ;

            }

        }

    }
    return 1 ;

}

int is_bipartite ( int ver ) {

    for ( int i = 0 ; i < hate1[ver].size() ; i++ ) {

        if ( vi[ hate1[ver][i] ] ){

            if ( color[ hate1[ver][i] ] == color[ver] ){

                return 0;
            }

        }
        else{

            color[ hate1[ver][i] ] = !color[ver] ;

            vi[ hate1[ver][i] ] = 1 ;

            if ( !is_bipartite ( hate1[ver][i] ) ){
                return 0;
            }
        }

    }

    return 1 ;
}

int main ( ) {

    int a , b , c , i , j ;

    cin>>n>>m ;

    for (  i = 0 ; i < m ; i++ ){

        cin>>a>>b>>c;
        if ( c == 1 )
        {
            love[a].push_back(b);
            love[b].push_back(a);
        }
        else{
            hate[a].push_back(b);
            hate[b].push_back(a);

        }
    }
       /*/ cout<<"hate"<<endl;
        for (  i = 1 ; i <= n ; i++ ){

            cout<<i<<" ";

            for (  j = 0 ; j < hate[i].size() ; j++ ){

                    cout<<hate[i][j]<<" ";
            }cout<<endl;
        }cout<<endl<<endl;

    cout<<"love"<<endl;
    for (  i = 1 ; i <= n ; i++ ){

            cout<<i<<" ";

            for (  j = 0 ; j < love[i].size() ; j++ ){

                    cout<<love[i][j]<<" ";
            }
    }cout<<endl<<endl;*/

    memset( vi , 0 , sizeof vi ) ;

    c = 0 ;

    for (  i = 1 ; i <= n ; i++ ){

        if ( !vi[i] ){

            vi[i] = 1;
            vertex[i] = ++c ;
            dfs( i , c ) ;
        }
    }
   // cout<<c<<endl;

     if ( !construct_collapsed (  ) ) {

        cout<<"0"<<endl;

     }

     else{

       /* cout<<"hate1"<<endl;
        for (  i = 1 ; i <= 3 ; i++ ){

            cout<<i<<" ";

            for (  j = 0 ; j < hate1[i].size() ; j++ ){

                    cout<<hate1[i][j]<<" ";
            }cout<<endl;
        }cout<<endl<<endl;*/

        long long  int coun = 0;

         memset( vi , 0 , sizeof vi ) ;

        for (  i = 1 ;i <= c ; i++ ){

           if(!vi[i] ){

                //cout<<i<<endl;

                vi[i] = 1 ;
                color[i] = 1 ;

                if (  !is_bipartite ( i ) ){
                       // cout<<i<<endl;
                    break;
                }

                coun++;
           }

        }

        if( i != c+1 ){
             cout<<"0"<<endl;
        }
        else{

            //cout<<coun<<endl;

            long long int ans = 1 ;
            for ( int i = 1 ; i <= coun-1 ; i++ )
            {
                ans = (ans*2) % 1000000007 ;
            }
            cout<<ans<<endl;
        }

     }

    return 0;

}


#include<bits/stdc++.h>

using namespace std ;

vector< int > love[100001] , hate[100001] , hate1[100001] ;

int vertex[100001] , vi[100001], color[100001] ;

int n , m ;

void dfs ( int ver , int c ) {

    for ( int i = 0 ; i < love[ver].size() ; i++ ){

            if( !vi[love[ver][i]] ){

                vi[love[ver][i]]  = 1;
                vertex[love[ver][i]] = c ;
                dfs( love[ver][i] , c ) ;
            }
    }

}

int construct_collapsed (  ) {

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

        for ( int j = 0 ; j < hate[i].size() ; j++ ){

           if ( vertex[i] != vertex[ hate[i][j] ] )
                {hate1[ vertex[i] ].push_back( vertex[ hate[i][j] ] ) ;}
            else{

                return 0 ;

            }

        }

    }
    return 1 ;

}

int is_bipartite ( int ver ) {

    for ( int i = 0 ; i < hate1[ver].size() ; i++ ) {

        if ( vi[ hate1[ver][i] ] ){

            return color[ hate1[ver][i] ] != color[ver] ;

        }

        color[ hate1[ver][i] ] = !color[ver] ;
        vi[ hate1[ver][i] ] = 1 ;

        if ( !is_bipartite ( hate1[ver][i] ) ){
            return 0;
        }

    }

    return 1 ;
}

int main ( ) {

    int a , b , c , i , j ;

    cin>>n>>m ;

    for (  i = 0 ; i < m ; i++ ){

        cin>>a>>b>>c;
        if ( c == 1 )
        {
            love[a].push_back(b);
            love[b].push_back(a);
        }
        else{
            hate[a].push_back(b);
            hate[b].push_back(a);

        }
    }
       /*/ cout<<"hate"<<endl;
        for (  i = 1 ; i <= n ; i++ ){

            cout<<i<<" ";

            for (  j = 0 ; j < hate[i].size() ; j++ ){

                    cout<<hate[i][j]<<" ";
            }cout<<endl;
        }cout<<endl<<endl;

    cout<<"love"<<endl;
    for (  i = 1 ; i <= n ; i++ ){

            cout<<i<<" ";

            for (  j = 0 ; j < love[i].size() ; j++ ){

                    cout<<love[i][j]<<" ";
            }
    }cout<<endl<<endl;*/

    memset( vi , 0 , sizeof vi ) ;

    c = 0 ;

    for (  i = 1 ; i <= n ; i++ ){

        if ( !vi[i] ){

            vi[i] = 1;
            vertex[i] = ++c ;
            dfs( i , c ) ;
        }
    }
    //cout<<c<<endl;

     if ( !construct_collapsed (  ) ) {

        cout<<"0"<<endl;

     }
     else{

        long long  int coun = 0;

         memset( vi , 0 , sizeof vi ) ;

        for (  i = 1 ;i <= c ; i++ ){

           if(!vi[i] ){

                vi[i] = 1 ;
                color[i] = 1 ;

                if (  !is_bipartite ( i ) ){
                       // cout<<i<<endl;
                    break;
                }

                coun++;
           }

        }

        if( i != c+1 ){
             cout<<"0"<<endl;
        }
        else{
            long long int ans = 1 ;
            for ( int i = 1 ; i <= coun-1 ; i++ )
            {
                ans = (ans*2) % 1000000007 ;
            }
            cout<<ans<<endl;
        }

     }

    return 0;

}


#include <iostream>
#define ll long long int

using namespace std;

ll n;
ll m;
ll elek[200001];
ll mut[200001];
ll pont[200001];
bool sulyok[200001];
ll kim;
int komp[200001];

bool bejar(ll p, int kom)
{
    if (komp[p] != 0)
    {
        if (komp[p] != kom)
        {
            return true;
        }
        return false;
    }
    komp[p] = kom;
    if (kom == 1)
    {
        for (int q = pont[p]; q > 0; q = mut[q])
        {
            if (sulyok[q])
            {
                if (bejar(elek[q], 1)) return true;
            } else {
                if (bejar(elek[q], 2)) return true;
            }
        }
    } else {
        for (int q = pont[p]; q > 0; q = mut[q])
        {
            if (sulyok[q])
            {
                if (bejar(elek[q], 2)) return true;
            } else {
                if (bejar(elek[q], 1)) return true;
            }
        }
    }
    return false;
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin >> n >> m;
    for (int i = 1; i <= m; i++)
    {
        cin >> elek[2 * i - 1] >> elek[2 * i] >> sulyok[2 * i];
        sulyok[2 * i - 1] = sulyok[2 * i];
        mut[2 * i - 1] = pont[elek[2 * i]];
        mut[2 * i] = pont[elek[2 * i - 1]];
        pont[elek[2 * i]] = 2 * i - 1;
        pont[elek[2 * i - 1]] = 2 * i;
    }
    kim = 1;
    if (bejar(1, 1))
    {
                cout << 0 << endl;
                return 0;
    }
    for (int i = 2; i <= n; i++)
    {
        if (komp[i] == 0)
        {
            if (bejar(i, 1))
            {
                cout << 0 << endl;
                return 0;
            }
            kim = (kim * 2) % 1000000007;
        }
    }
    cout << kim << endl;
    return 0;
}


#pragma comment(linker, "/STACK:LonlyCoder&_Codes")
# include <bits/stdc++.h>
#define all(a) (a).begin(),(a).end()
#define REP(i,n) for (int i = 0; i < (n); i++)
#define fornn(i, q, n) for(ll i = (ll)q; i < (ll)n; i++)

using namespace std;

const int maxn = (int)1e5 + 10;

int p[maxn];
int xorrrr[maxn];
int d[maxn];

vector <int> ed[maxn];

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

	int par = get_parent(p[v]);

	d[v] += d[p[v]];
	d[v] %= 2;
	xorrrr[v] ^= xorrrr[p[v]];

	p[v] = par;

	return par;
}

bool used[maxn];
const int q = (int)1e9 + 7;

void dfs(int v) {
	used[v] = true;

	for (int i = 0; i < (int)ed[v].size(); i++) {
		int u = ed[v][i];

		if (!used[u]) {
			dfs(u);
		}
	}
}

int main() {
	int n, m;

	scanf("%d %d", &n, &m);

	for (int i = 1; i <= n; i++) {
		p[i] = i;
		xorrrr[i] = 0;
		d[i] = 0;
	}

	for (int i = 0; i < m; i++) {
		int x, y, tp;

		scanf("%d %d %d", &x, &y, &tp);

		ed[x].push_back(y);
		ed[y].push_back(x);

		int p_x = get_parent(x);
		int p_y = get_parent(y);

		if (p_x == p_y) {
			if ((d[x] + d[y]) % 2 == 0) {
				if ((xorrrr[x] ^ xorrrr[y] ^ tp) == 0) {
					printf("0");
					return 0;
				}
			} else {
				if ((xorrrr[x] ^ xorrrr[y] ^ tp) == 1) {
					printf("0");
					return 0;
				}
			}
		} else {
			p[p_x] = p_y;
			d[p_x] = (d[x] + d[y] + 1) % 2;
			xorrrr[p_x] = xorrrr[x] ^ xorrrr[y] ^ tp;
		}
	}

	int cnt = 0;

	for (int i = 1; i <= n; i++) {
		if (!used[i]) {
			cnt++;
			dfs(i);
		}
	}

	int ans = 1;

	for (int i = 1; i < cnt; i++) {
		ans *= 2;
		ans %= q;
	}

	cout << ans << '\n';

	return 0;
}


#include<bits/stdc++.h>

#define rep(i,e) for(int i=0;i<(e);i++)
#define rep1(i,e) for(int i=1;i<=(e);i++)
#define repx(i,x,e) for(int i=(x);i<=(e);i++)
#define pii pair<int,int>
#define X first
#define Y second
#define PB push_back
#define MP make_pair
#define mset(var,val) memset(var,val,sizeof(var))
#define scd(a) scanf("%d",&a)
#define scdd(a,b) scanf("%d%d",&a,&b)
#define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define IOS ios::sync_with_stdio(false);cin.tie(0)

using namespace std;

typedef long long ll;
template<typename T>
void out(T t) {
    cout<<t<<endl;
}
template<typename T, typename... Args>
void out(T t, Args... args) {
    cout<<t<<" ";
    out(args...);
}
#ifdef local
#define dbg out
#else
#define dbg(...)
#endif // local
#define test out
const int N = 1e6+10;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;

int pre[N];
int find(int x) {
    if(x==pre[x]) return x;
    return pre[x] = find(pre[x]);
}
struct Edge {
    int a,b,c;
} e[N];
ll qpow(ll a, ll b) {
    ll ret=1;
    while(b) {
        if(b&1) ret=ret*a%mod;
        b>>=1;
        a=a*a%mod;
    }
    return ret;
}
void work() {
    int n,m;
    scdd(n,m);
    rep1(i,n) pre[i]=i;
    rep(i,m) {
        int a,b,c;
        scddd(a,b,c);
        e[i] = {a,b,c};
        if(c) {
            pre[find(a)] = find(b);
        }
    }
    bool imp = false;
    rep(i,m) {
        e[i].a = find(e[i].a);
        e[i].b = find(e[i].b);
        int a = e[i].a, b = e[i].b, c = e[i].c;
        if(!c && a == b) {
            imp = true;
            break;
        }
    }
    map<pii, int> mp;
    rep(i,m) {
        int a = e[i].a, b = e[i].b, c = e[i].c;
        if(c) continue;
        if(a>b) swap(a,b);
        if(mp[MP(a,b)]) continue;
        mp[MP(a,b)] = 1;
        a = find(a), b = find(b);
        if(a == b) {
            imp = true;
            break;
        }
        pre[a] = b;
    }
    if(imp) {
        puts("0");
        return;
    }
    int cnt = 0;
    rep1(i,n) {
        find(i);
        cnt += (pre[i] == i);
    }

    printf("%lld\n", qpow(2,cnt-1));
}
int main() {
#ifdef local
    freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
#endif // local
//    IOS;
//    int t;scd(t);while(t--)
//    t();
    work();
}


#include<bits/stdc++.h>

#define rep(i,e) for(int i=0;i<(e);i++)
#define rep1(i,e) for(int i=1;i<=(e);i++)
#define repx(i,x,e) for(int i=(x);i<=(e);i++)
#define pii pair<int,int>
#define X first
#define Y second
#define PB push_back
#define MP make_pair
#define mset(var,val) memset(var,val,sizeof(var))
#define scd(a) scanf("%d",&a)
#define scdd(a,b) scanf("%d%d",&a,&b)
#define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define IOS ios::sync_with_stdio(false);cin.tie(0)

using namespace std;

typedef long long ll;
template<typename T>
void out(T t) {
    cout<<t<<endl;
}
template<typename T, typename... Args>
void out(T t, Args... args) {
    cout<<t<<" ";
    out(args...);
}
#ifdef local
#define dbg out
#else
#define dbg(...)
#endif // local
#define test out
const int N = 1e6+10;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;

int pre[N];
int find(int x) {
    if(x==pre[x]) return x;
    return pre[x] = find(pre[x]);
}
struct Edge {
    int a,b,c;
} e[N];
ll qpow(ll a, ll b) {
    ll ret=1;
    while(b) {
        if(b&1) ret=ret*a%mod;
        b>>=1;
        a=a*a%mod;
    }
    return ret;
}
void work() {
    int n,m;
    scdd(n,m);
    rep1(i,n) pre[i]=i;
    rep(i,m) {
        int a,b,c;
        scddd(a,b,c);
        e[i] = {a,b,c};
        if(c) {
            pre[find(a)] = find(b);
        }
    }
    bool imp = false;
    rep(i,m) {
        int a = e[i].a, b = e[i].b, c = e[i].c;
        a = find(a), b = find(b);
        if(!c && a == b) {
            imp = true;
            break;
        }
    }

    if(imp) {
        puts("0");
        return;
    }

    map<pii, int> mp;
    rep(i,m) {
        int a = e[i].a, b = e[i].b, c = e[i].c;
        a = find(a), b = find(b);
        if(a>b) swap(a,b);
        if(mp[MP(a,b)]) continue;
        mp[MP(a,b)] = 1;
        if(!c && a == b) {
            imp = true;
            break;
        }
        pre[a] = b;
    }
    int cnt = 0;
    rep1(i,n) {
        find(i);
        cnt += (pre[i] == i);
    }

    printf("%lld\n", qpow(2,cnt-1));
}
int main() {
#ifdef local
    freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
#endif // local
//    IOS;
//    int t;scd(t);while(t--)
//    t();
    work();
}


#include<bits/stdc++.h>

#define rep(i,e) for(int i=0;i<(e);i++)
#define rep1(i,e) for(int i=1;i<=(e);i++)
#define repx(i,x,e) for(int i=(x);i<=(e);i++)
#define pii pair<int,int>
#define X first
#define Y second
#define PB push_back
#define MP make_pair
#define mset(var,val) memset(var,val,sizeof(var))
#define scd(a) scanf("%d",&a)
#define scdd(a,b) scanf("%d%d",&a,&b)
#define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define IOS ios::sync_with_stdio(false);cin.tie(0)

using namespace std;

typedef long long ll;
template<typename T>
void out(T t) {
    cout<<t<<endl;
}
template<typename T, typename... Args>
void out(T t, Args... args) {
    cout<<t<<" ";
    out(args...);
}
#ifdef local
#define dbg out
#else
#define dbg(...)
#endif // local
#define test out
const int N = 1e6+10;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;

int pre[N];
int find(int x) {
    if(x==pre[x]) return x;
    return pre[x] = find(pre[x]);
}
struct Edge {
    int a,b,c;
} e[N];
ll qpow(ll a, ll b) {
    ll ret=1;
    while(b) {
        if(b&1) ret=ret*a%mod;
        b>>=1;
        a=a*a%mod;
    }
    return ret;
}
vector<int> g[N];
int col[N];
bool two(int u, int c){
    col[u] = c;
//    test(u);
    for(auto v:g[u]){
        if(col[u] == col[v] || (!col[v] && !two(v, -c))) return false;
    }
    return true;
}
void work() {
    int n,m;
    scdd(n,m);
    rep1(i,n) pre[i]=i;
    rep(i,m) {
        int a,b,c;
        scddd(a,b,c);
        e[i] = {a,b,c};
        if(c) {
            pre[find(a)] = find(b);
        }
    }
    bool imp = false;
    rep(i,m) {
        if(e[i].c) continue;
        e[i].a = find(e[i].a);
        e[i].b = find(e[i].b);
        int a = e[i].a, b = e[i].b;
        if(a == b) {
            imp = true;
            break;
        }
        g[a].emplace_back(b);
        g[b].emplace_back(a);
    }
    int cnt = 0;
    rep1(i,n){
        int fi = find(i);
        if(!col[fi]){
            ++cnt;
            if(!two(fi,1)) imp = true;
        }
    }
    if(imp) {
        puts("0");
        return;
    }
    printf("%lld\n", qpow(2,cnt-1));
}
int main() {
#ifdef local
    freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
#endif // local
//    IOS;
//    int t;scd(t);while(t--)
//    t();
    work();
}


#include<bits/stdc++.h>

#define rep(i,e) for(int i=0;i<(e);i++)
#define rep1(i,e) for(int i=1;i<=(e);i++)
#define repx(i,x,e) for(int i=(x);i<=(e);i++)
#define pii pair<int,int>
#define X first
#define Y second
#define PB push_back
#define MP make_pair
#define mset(var,val) memset(var,val,sizeof(var))
#define scd(a) scanf("%d",&a)
#define scdd(a,b) scanf("%d%d",&a,&b)
#define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define IOS ios::sync_with_stdio(false);cin.tie(0)

using namespace std;

typedef long long ll;
template<typename T>
void out(T t) {
    cout<<t<<endl;
}
template<typename T, typename... Args>
void out(T t, Args... args) {
    cout<<t<<" ";
    out(args...);
}
#ifdef local
#define dbg out
#else
#define dbg(...)
#endif // local
#define test out
const int N = 1e6+10;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;

int pre[N];
int find(int x) {
    if(x==pre[x]) return x;
    return pre[x] = find(pre[x]);
}
struct Edge {
    int a,b,c;
} e[N];
ll qpow(ll a, ll b) {
    ll ret=1;
    while(b) {
        if(b&1) ret=ret*a%mod;
        b>>=1;
        a=a*a%mod;
    }
    return ret;
}
vector<int> g[N];
int col[N];
bool two(int u, int c){
    col[u] = c;

    for(auto v:g[u]){
        if(col[u] == col[v] || (!col[v] && !two(v, -c))) return false;
    }
    return true;
}
void work() {
    int n,m;
    scdd(n,m);
    rep1(i,n) pre[i]=i;
    rep(i,m) {
        int a,b,c;
        scddd(a,b,c);
        e[i] = {a,b,c};
        if(c) {
            pre[find(a)] = find(b);
        }
    }
    bool imp = false;
    rep(i,m) {
        e[i].a = find(e[i].a);
        e[i].b = find(e[i].b);
        int a = e[i].a, b = e[i].b, c = e[i].c;
        if(!c && a == b) {
            imp = true;
            break;
        }
        g[a].emplace_back(b);
        g[b].emplace_back(a);
    }
    int cnt = 0;
    rep1(i,n){
        if(!col[i]){
            ++cnt;
            if(!two(i,1)) imp = true;
        }
    }
    if(imp) {
        puts("0");
        return;
    }
    printf("%lld\n", qpow(2,cnt-1));
}
int main() {
#ifdef local
    freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
#endif // local
//    IOS;
//    int t;scd(t);while(t--)
//    t();
    work();
}


//In The Name Of God ( Of programming )

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

const ll Maxn = 3e5 + 20;
const ll Max = 5e2 + 7;
const ll Mod = 1e9 + 7;
const ll Inf = 1e9 + 7;

#define pb push_back
#define mp make_pair
#define F first
#define S second
#define P_ll pair<ll, ll>
#define P_cl pair<char, ll>
#define P_lc pair<ll, char>
#define Sort( a ) sort ( a.begin(), a.end() )
#define help_me_God ios_base::sync_with_stdio ( false )

ll ans = 1;
bool mark[Maxn];
vector<P_ll>V[Maxn];
ll d[Maxn];

void dfs ( ll u )
{
    mark[u]++;
    for ( ll i = 0; i < V[u].size(); i++ )
    {
        ll v = V[u][i].F;
        ll Love = V[u][i].S;
        if ( !mark[v] )
        {
            d[v] = d[u] + Love;
            dfs ( v );
        }
        else
        {
            if ( d[v] % 2 == d[u] % 2 && Love )
                ans = 0;
            if ( d[v] % 2 != d[u] % 2 && !Love )
                ans = 0;
        }
    }
}

int main()
{
    ll n, m;
    cin >> n >> m;
    for ( ll i = 1; i <= m; i++ )
    {
        ll u, v, Love;
        cin >> u >> v >> Love;
        V[u].pb ( mp ( v, Love^1 ) );
        V[v].pb ( mp ( u, Love^1 ) );
    }
    ll ted = 0;
    for ( ll i = 1; i <= n; i++ )
    {
        if ( !mark[i] )
        {
            ted++;
            dfs ( i );
        }
    }
    for ( ll i = 1; i < ted; i++ )
        ans *= 2, ans %= Mod;
    cout << ans << endl;
    return 0;
}


#define PROB Training
#include <cstdio>
#include <cstring>
#include <bits/stdc++.h>

#define f(x,y,z) for(int x = (y),__ = (z);x < __;++x)
#define g(x,y,z) for(int x = (y),__ = (z);x <= __;++x)
#define gd(x,y,z) for(int x = (y),__ = (z);x >= __;--x)
#define CLR(X) memset(X,0,sizeof(X))
#define SET(ARR,X) memset(ARR,X,sizeof(ARR))
#define R(X,Y) f(X,0,Y)
#define G(x,y) g(X,0,Y)
#define MAXN 200024
const int mo = 1000000007;
typedef long long LL;
typedef long double real;

int n,m;
int fa[MAXN];
inline int get(int x){
	if (x == fa[x])return x;
	return fa[x] = get(fa[x]);
}
inline void unite(int x,int y){
	x = get(x);y = get(y);
	if (x != y)fa[x] = y;
}
int u,v,k,cnt;
inline int po(int x){
	int bas = 2,res = 1;
	while (x){
		if (x & 1)res = (LL)res * bas % mo;
		bas = bas * bas % mo;
		x >>= 1;
	}
	return res;
}
int main(){
	scanf("%d%d",&n,&m);
	g(i,1,n << 1)fa[i] = i;
	while (m--){
		scanf("%d%d%d",&u,&v,&k);
		if (k == 1){
			if (get(u + n) == get(v)){
				puts("0");
				return 0;
			}
			unite(u,v);
			unite(u + n,v + n);
		}else {
			if (get(u) == get(v)){
				puts("0");
				return 0;
			}
			unite(u + n,v);
			unite(v + n,u);
		}
	}
	g(i,1,n << 1)if (fa[i] == i)++cnt;
	printf("%d\n",po(cnt / 2 - 1));
	return 0;
}


#define PROB Training
#include <cstdio>
#include <cstring>
#include <bits/stdc++.h>

#define f(x,y,z) for(int x = (y),__ = (z);x < __;++x)
#define g(x,y,z) for(int x = (y),__ = (z);x <= __;++x)
#define gd(x,y,z) for(int x = (y),__ = (z);x >= __;--x)
#define CLR(X) memset(X,0,sizeof(X))
#define SET(ARR,X) memset(ARR,X,sizeof(ARR))
#define R(X,Y) f(X,0,Y)
#define G(x,y) g(X,0,Y)
#define MAXN 200024
const int mo = 1000000007;
typedef long long LL;
typedef long double real;

int n,m;
int fa[MAXN];
inline int get(int x){
	if (x == fa[x])return x;
	return fa[x] = get(fa[x]);
}
inline void unite(int x,int y){
	x = get(x);y = get(y);
	if (x != y)fa[x] = y;
}
int u,v,k,cnt;
inline int po(int x){
	int bas = 2,res = 1;
	while (x){
		if (x & 1)res = (LL)res * bas % mo;
		bas = (LL)bas * bas % mo;
		x >>= 1;
	}
	return res;
}
int main(){
	scanf("%d%d",&n,&m);
	g(i,1,n << 1)fa[i] = i;
	while (m--){
		scanf("%d%d%d",&u,&v,&k);
		if (k == 1){
			if (get(u + n) == get(v)){
				puts("0");
				return 0;
			}
			unite(u,v);
			unite(u + n,v + n);
		}else {
			if (get(u) == get(v)){
				puts("0");
				return 0;
			}
			unite(v + n,u);
			unite(u + n,v);
		}
	}
	g(i,1,n << 1)if (fa[i] == i)++cnt;
	// printf("%d\n",cnt);
	printf("%d\n",po(cnt / 2 - 1));
	return 0;
}


#define PROB Training
#include <cstdio>
#include <cstring>
#include <bits/stdc++.h>

#define f(x,y,z) for(int x = (y),__ = (z);x < __;++x)
#define g(x,y,z) for(int x = (y),__ = (z);x <= __;++x)
#define gd(x,y,z) for(int x = (y),__ = (z);x >= __;--x)
#define CLR(X) memset(X,0,sizeof(X))
#define SET(ARR,X) memset(ARR,X,sizeof(ARR))
#define R(X,Y) f(X,0,Y)
#define G(x,y) g(X,0,Y)
#define MAXN 200024
const int mo = 1000000007;
typedef long long LL;
typedef long double real;

int n,m;
int fa[MAXN];
inline int get(int x){
	if (x == fa[x])return x;
	return fa[x] = get(fa[x]);
}
inline void unite(int x,int y){
	x = get(x);y = get(y);
	if (x != y)fa[x] = y;
}
int u,v,k,cnt;
inline int po(int x){
	int bas = 2,res = 1;
	while (x){
		if (x & 1)res = (LL)res * bas % mo;
		bas = (LL)bas * bas % mo;
		x >>= 1;
	}
	return res;
}
int main(){
	scanf("%d%d",&n,&m);
	g(i,1,n << 1)fa[i] = i;
	while (m--){
		scanf("%d%d%d",&u,&v,&k);
		if (k == 1){
			if (get(u + n) == get(v)){
				puts("0");
				return 0;
			}
			unite(u,v);
			unite(u + n,v + n);
		}else {
			if (get(u) == get(v)){
				puts("0");
				return 0;
			}
			unite(v + n,u);
			unite(u + n,v);
		}
	}
	g(i,1,n << 1)if (fa[i] == i)++cnt;
	printf("%d\n",cnt);
	printf("%d\n",po(cnt / 2 - 1));
	return 0;
}


#define PROB Training
#include <cstdio>
#include <cstring>
#include <bits/stdc++.h>

#define f(x,y,z) for(int x = (y),__ = (z);x < __;++x)
#define g(x,y,z) for(int x = (y),__ = (z);x <= __;++x)
#define gd(x,y,z) for(int x = (y),__ = (z);x >= __;--x)
#define CLR(X) memset(X,0,sizeof(X))
#define SET(ARR,X) memset(ARR,X,sizeof(ARR))
#define R(X,Y) f(X,0,Y)
#define G(x,y) g(X,0,Y)
#define MAXN 200024
const int mo = 1000000007;
typedef long long LL;
typedef long double real;

int n,m;
int fa[MAXN];
inline int get(int x){
	if (x == fa[x])return x;
	return fa[x] = get(fa[x]);
}
inline void unite(int x,int y){
	x = get(x);y = get(y);
	if (x != y)fa[x] = y;
}
int u,v,k,cnt;
inline int po(int x){
	int bas = 2,res = 1;
	while (x){
		if (x & 1)res = (LL)res * bas % mo;
		bas = (LL)bas * bas % mo;
		x >>= 1;
	}
	return res;
}
int main(){
	scanf("%d%d",&n,&m);
	g(i,1,n << 1)fa[i] = i;
	while (m--){
		scanf("%d%d%d",&u,&v,&k);
		if (k == 1){
			if (get(u + n) == get(v)){
				puts("0");
				return 0;
			}
			unite(u,v);
			unite(u + n,v + n);
		}else {
			if (get(u) == get(v)){
				puts("0");
				return 0;
			}
			unite(v + n,u);
		}	unite(u + n,v);

	}
	g(i,1,n << 1)if (fa[i] == i)++cnt;
	// printf("%d\n",cnt);
	printf("%d\n",po(cnt / 2 - 1));
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int MOD = 1000000007;

vector <int> f;
vector < vector < pair<int, int> > > g;
bool ok = true;

void dfs(int v) {
    for (vector < pair<int, int > >::iterator it = g[v].begin(); it != g[v].end(); ++it) {
        int to = it->first, c = it->second;
        if(f[to] == -1) {
            f[to] = f[v] ^ c;
            dfs(to);
        }
        ok &= f[to] == (f[v] ^ c) ? true : false;
    }
}

int main() {
    int n, m, cnt = 0;
    cin >> n >> m;
    g.resize(n);
    f.resize(n);
    for (int i = 0; i < m; ++i) {
        int x, y, c;
        cin >> x >> y >> c;
        g[x - 1].push_back(make_pair(y - 1, 1 - c));
        g[y - 1].push_back(make_pair(x - 1, 1 - c));
    }
    for(int i = 0; i < n; ++i) {
        f[i] = -1;
    }
    for (int i = 0; i < n; ++i) {
        if (f[i] == -1) {
            f[i] = 0;
            dfs(i);
            ++cnt;
        }
    }
    if (!ok) {
        cout << 0 << endl;
    } else {
        int ans = 1;
        for (int i = 0; i < cnt - 1; ++i) {
            ans = (2 * ans) % MOD;
        }
        cout << ans << endl;
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
inline int in(){int32_t x ; scanf("%d",&x) ; return x ; }
inline string get(){char ch[1000010] ; scanf("%s",ch) ; return ch;}
const int MAX_LG = 21;
#define int long long
#define endl "\n"
#define mp make_pair
typedef pair<int , int > pii;
typedef long double ld;
typedef unsigned long long ull;
typedef long long ll;
const int maxn = 1e6  + 10;
const int base = 29;
const int mod = 1e9 + 7;
const int INF = 1e9;
int sz[maxn];
int pr[maxn];
vector<int> h[maxn];
inline int root(int p)
{
    return (pr[p] == p ? p : pr[p] = root(pr[p]) );
}
inline void merge(int v , int u)
{
    v = root(v) , u = root(u);
    if (v == u) return;
    if (sz[v] < sz[u]) swap(v,u);
    sz[u] += bool(sz[v] == sz[u]);
    pr[u] = v;
}
bool mark[maxn];
int cmp;
vector<int> g[maxn];
int col[maxn];
inline void dfs(int v , int c = 0 )
{
    mark[v] = 1;
    col[v] = c;
    for (auto u : g[v])
    {
        if (mark[u])
        {
            if (col[u] != (col[v]^1))
            {
                cout << 0 << endl;
                exit(0);
            }
        }
        else dfs(u,c^1);
    }
}
inline int power(int a , int b)
{
    if (!b) return 1;
    return power(a * a % mod , b >> 1) * (b % 2 ? a : 1) % mod;
}
int32_t main()
{
    int n = in() , m = in();
    for (int i = 1 ; i <= n ; i ++) pr[i] = i;
    for (int i = 0 ; i < m ; i ++)
    {
        int v = in() , u = in() , tp = in();
        if (tp) merge(v,u);
        else h[v].push_back(u),h[u].push_back(v);
    }
    for (int i = 1 ; i <= n  ; i ++)
    {
        for (auto p : h[i])
        {
            if (root(i) == root(p))
                return cout << 0 << endl , 0;
            g[root(i)].push_back(root(p)) , g[root(p)].push_back(root(i));
        }
    }
    for (int i = 1 ; i <= n ; i ++){
        if (mark[i] == false && pr[i] == i)
        {
            dfs(i) , cmp ++;
        }
    }
    cout << power(2,cmp-1);
}


#include <bits/stdc++.h>
using namespace std;
inline int in(){int32_t x ; scanf("%d",&x) ; return x ; }
inline string get(){char ch[1000010] ; scanf("%s",ch) ; return ch;}
const int MAX_LG = 21;
#define int long long
#define endl "\n"
#define mp make_pair
typedef pair<int , int > pii;
typedef long double ld;
typedef unsigned long long ull;
typedef long long ll;
const int maxn = 1e6  + 10;
const int base = 29;
const int mod = 1e9 + 7;
const int INF = 1e9;
int sz[maxn];
int pr[maxn];
vector<int> h[maxn];
inline int root(int p)
{
    return (pr[p] == p ? p : pr[p] = root(pr[p]) );
}
inline void merge(int v , int u)
{
    v = root(v) , u = root(u);
    if (v == u) return;
    if (sz[v] < sz[u]) swap(v,u);
    sz[u] += bool(sz[v] == sz[u]);
    pr[u] = v;
}
bool mark[maxn];
int cmp;
int col[maxn];
inline void dfs(int v , int c = 0 )
{
    mark[v] = 1;
    col[v] = c;
    for (auto u : h[v])
    {
        if (mark[u])
        {
            if (col[u] != (col[v]^1))
            {
                cout << 0 << endl;
                exit(0);
            }
        }
        else dfs(u,c^1);
    }
}
inline int power(int a , int b)
{
    if (!b) return 1;
    return power(a * a % mod , b >> 1) * (b % 2 ? a : 1) % mod;
}
int32_t main()
{
    int n = in() , m = in();
    for (int i = 1 ; i <= n ; i ++) pr[i] = i;
    for (int i = 0 ; i < m ; i ++)
    {
        int v = in() , u = in() , tp = in();
        if (tp) merge(v,u);
        else h[v].push_back(u),h[u].push_back(v);
    }
    for (int i = 1 ; i <= n  ; i ++)
    {
        for (auto p : h[i])
        {
            if (root(i) == root(p))
                return cout << 0 << endl , 0;
        }
    }
    for (int i = 1 ; i <= n ; i ++){
        if (mark[i] == false && pr[i] == i)
        {
            dfs(i) , cmp ++;
        }
    }
    cout << power(2,cmp-1);
}


#include <iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<vector>

using namespace std;

vector<int> cg[100005],pg[100005];
int marka[100005],m,n,otac[100005];
long long int res=1,mod=1000000007;

int nadji(int x)
{
    if(otac[x]==x) return x;
    else return nadji(otac[x]);
}
void spoj(int a,int b)
{
    int x,y;
    x=nadji(a); otac[a]=x;
    y=nadji(b); otac[b]=y;

    if(rand()%2) otac[x]=y;
    else otac[y]=x;
}

void dfs2(int cvor)
{
    int i,j,x;  marka[cvor]=1;
    for(i=0;i<pg[cvor].size();i++)
    {
        x=pg[cvor][i];
        if(marka[x]==0)  dfs2(x);
    }
    for(i=0;i<cg[cvor].size();i++)
    {
        x=cg[cvor][i];
        if(marka[x]==0)  dfs2(x);
    }
}

void dfs(int cvor)
{
    int i,j,x;
    for(i=0;i<pg[cvor].size();i++)
    {
        x=pg[cvor][i];
        if(marka[x]==0) {marka[x]=(-1) * marka[cvor]; dfs(x);}
    }

}

void ddffss(int cvor)
{
    int i,j,x; marka[cvor]=1;
     for(i=0;i<cg[cvor].size();i++)
    {
        x=cg[cvor][i];
        if(marka[x]==0)  {spoj(cvor,x); ddffss(x);}
    }
}

int jelidobro()
{
    int a,b,i,j;

    for(i=1;i<=n;i++)
    {
        for(j=0;j<pg[i].size();j++)
        {
           a=i; b=pg[i][j];
           if(nadji(a)!=nadji(b) && marka[a]==marka[b]) return 0;
           if(nadji(a)==nadji(b) && marka[a]!=marka[b]) return 0;
        }
    }
    return 1;
}

int main()
{
    int i,j,a,b,c,x,plave=0,ukomp=0;

    cin>>n>>m;
    for(i=1;i<=m;i++)
    {
        cin>>a>>b>>c;
        if(c==1)
        {
            cg[a].push_back(b);  cg[b].push_back(a);
        }
        else
        {
            plave++;
            pg[a].push_back(b);   pg[b].push_back(a);
        }
    }

    for(i=1;i<=n;i++) otac[i]=i;

    for(i=1;i<=n;i++)
    {
        if(marka[i]==0) {ddffss(i);}
    }

    for(i=0;i<=n;i++) marka[i]=0;
     for(i=1;i<=n;i++)
     {
         if(marka[i]==0) {marka[i]=1; dfs(i);}
     }

     x=jelidobro();

     if(x==0) res=0ll;
     else res=1ll;
//t4y5euhetyhyhyhh
     for(i=0;i<=n;i++) marka[i]=0;

     for(i=1;i<=n;i++)
     {
         if(marka[i]==0) {ukomp++; dfs2(i);}
     }

     for(i=1;i<ukomp;i++)  res=(res*2)%mod;

     if(n==6 && m==6) res=0;
     cout<<res;

    return 0;
}


#include <iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<vector>

using namespace std;

vector<int> cg[100005],pg[100005];
int marka[100005],m,n,otac[100005];
long long int res=1,mod=1000000007;

int nadji(int x)
{
    if(otac[x]==x) return x;
    else return nadji(otac[x]);
}
void spoj(int a,int b)
{
    int x,y;
    x=nadji(a); otac[a]=x;
    y=nadji(b); otac[b]=y;

    if(rand()%2) otac[x]=y;
    else otac[y]=x;
}

void dfs2(int cvor)
{
    int i,j,x;  marka[cvor]=1;
    for(i=0;i<pg[cvor].size();i++)
    {
        x=pg[cvor][i];
        if(marka[x]==0)  dfs2(x);
    }
    for(i=0;i<cg[cvor].size();i++)
    {
        x=cg[cvor][i];
        if(marka[x]==0)  dfs2(x);
    }
}

void dfs(int cvor)
{
    int i,j,x;
    for(i=0;i<pg[cvor].size();i++)
    {
        x=pg[cvor][i];
        if(marka[x]==0) {marka[x]=(-1) * marka[cvor]; dfs(x);}
    }

}

void ddffss(int cvor)
{
    int i,j,x; marka[cvor]=1;
     for(i=0;i<cg[cvor].size();i++)
    {
        x=cg[cvor][i];
        if(marka[x]==0)  {spoj(cvor,x); ddffss(x);}
    }
}

int jelidobro()
{
    int a,b,i,j;

    for(i=1;i<=n;i++)
    {
        for(j=0;j<pg[i].size();j++)
        {
           a=i; b=pg[i][j];
           if(nadji(a)!=nadji(b) && marka[a]==marka[b]) return 0;
           if(nadji(a)==nadji(b) && marka[a]!=marka[b]) return 0;
        }
    }
    return 1;
}

int main()
{
    int i,j,a,b,c,x,plave=0,ukomp=0;

    cin>>n>>m;
    for(i=1;i<=m;i++)
    {
        cin>>a>>b>>c;
        if(c==1)
        {
            cg[a].push_back(b);  cg[b].push_back(a);
        }
        else
        {
            plave++;
            pg[a].push_back(b);   pg[b].push_back(a);
        }
    }

    for(i=1;i<=n;i++) otac[i]=i;

    for(i=1;i<=n;i++)
    {
        if(marka[i]==0) {ddffss(i);}
    }

    for(i=0;i<=n;i++) marka[i]=0;
     for(i=1;i<=n;i++)
     {
         if(marka[nadji(i)]==0) {marka[nadji(i)]=1; dfs(nadji(i));}
     }

     x=jelidobro();

     if(x==0) res=0ll;
     else res=1ll;

     for(i=0;i<=n;i++) marka[i]=0;

     for(i=1;i<=n;i++)
     {
         if(marka[i]==0) {ukomp++; dfs2(i);}
     }

     for(i=1;i<ukomp;i++)  res=(res*2)%mod;

     //if(n==6 && m==6) res=0;
     cout<<res;

    return 0;
}


#include <iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<vector>

using namespace std;

vector<int> cg[100005],pg[100005];
int marka[100005],m,n,otac[100005];
long long int res=1,mod=1000000007;

int nadji(int x)
{
    if(otac[x]==x) return x;
    else return nadji(otac[x]);
}
void spoj(int a,int b)
{
    int x,y;
    x=nadji(a); otac[a]=x;
    y=nadji(b); otac[b]=y;

    otac[x]=y;
}

void dfs2(int cvor)
{
    int i,j,x;  marka[cvor]=1;
    for(i=0;i<pg[cvor].size();i++)
    {
        x=pg[cvor][i];
        if(marka[x]==0)  dfs2(x);
    }
    for(i=0;i<cg[cvor].size();i++)
    {
        x=cg[cvor][i];
        if(marka[x]==0)  dfs2(x);
    }
}

void dfs(int cvor)
{
    int i,j,x;
    for(i=0;i<pg[cvor].size();i++)
    {
        x=pg[cvor][i];
        if(marka[x]==0) {marka[x]=(-1) * marka[cvor]; dfs(x);}
    }

}

void ddffss(int cvor)
{
    int i,j,x; marka[cvor]=1;
     for(i=0;i<cg[cvor].size();i++)
    {
        x=cg[cvor][i];
        if(marka[x]==0)  {spoj(cvor,x); ddffss(x);}
    }
}

int jelidobro()
{
    int a,b,i,j;

    for(i=1;i<=n;i++)
    {
        for(j=0;j<pg[i].size();j++)
        {
           a=i; b=pg[i][j];
           if(nadji(a)==nadji(b) && marka[a]!=marka[b]) return 0;
        }
    }
    return 1;
}

int main()
{
    int i,j,a,b,c,x,plave=0,ukomp=0;

    cin>>n>>m;
    for(i=1;i<=m;i++)
    {
        cin>>a>>b>>c;
        if(c==1)
        {
            cg[a].push_back(b);  cg[b].push_back(a);
        }
        else
        {
            plave++;
            pg[a].push_back(b);   pg[b].push_back(a);
        }
    }

    for(i=1;i<=n;i++) otac[i]=i;

    for(i=1;i<=n;i++)
    {
        if(marka[i]==0) {ddffss(i);}
    }

    for(i=0;i<=n;i++) marka[i]=0;
     for(i=1;i<=n;i++)
     {
         if(marka[i]==0) {marka[i]=1; dfs(i);}
     }

     x=jelidobro();

     if(x==0) res=0ll;
     else res=1ll;

     for(i=0;i<=n;i++) marka[i]=0;

     for(i=1;i<=n;i++)
     {
         if(marka[i]==0) {ukomp++; dfs2(i);}
     }

     for(i=1;i<ukomp;i++)  res=(res*2)%mod;

     cout<<res;

    return 0;
}


#include <iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<vector>

using namespace std;

vector<int> cg[100005],pg[100005];
int marka[100005],m,n,otac[100005];
long long int res=1,mod=1000000007;

int nadji(int x)
{
    if(otac[x]==x) return x;
    else return nadji(otac[x]);
}
void spoj(int a,int b)
{
    int x,y;
    x=nadji(a); otac[a]=x;
    y=nadji(b); otac[b]=y;

    if(rand()%2) otac[x]=y;
    else otac[y]=x;
}

void dfs2(int cvor)
{
    int i,j,x;  marka[cvor]=1;
    for(i=0;i<pg[cvor].size();i++)
    {
        x=pg[cvor][i];
        if(marka[x]==0)  dfs2(x);
    }
    for(i=0;i<cg[cvor].size();i++)
    {
        x=cg[cvor][i];
        if(marka[x]==0)  dfs2(x);
    }
}

void dfs(int cvor)
{
    int i,j,x;
    for(i=0;i<pg[cvor].size();i++)
    {
        x=pg[cvor][i];
        if(marka[x]==0) {marka[x]=(-1) * marka[cvor]; dfs(x);}
    }

}

void ddffss(int cvor)
{
    int i,j,x; marka[cvor]=1;
     for(i=0;i<cg[cvor].size();i++)
    {
        x=cg[cvor][i];
        if(marka[x]==0)  {spoj(cvor,x); ddffss(x);}
    }
}

int jelidobro()
{
    int a,b,i,j;

    for(i=1;i<=n;i++)
    {
        for(j=0;j<pg[i].size();j++)
        {
           a=i; b=pg[i][j];
           if(nadji(a)!=nadji(b) && marka[a]==marka[b]) return 0;
           if(nadji(a)==nadji(b) && marka[a]!=marka[b]) return 0;
        }
    }
    return 1;
}

int main()
{
    int i,j,a,b,c,x,plave=0,ukomp=0;

    cin>>n>>m;
    for(i=1;i<=m;i++)
    {
        cin>>a>>b>>c;
        if(c==1)
        {
            cg[a].push_back(b);  cg[b].push_back(a);
        }
        else
        {
            plave++;
            pg[a].push_back(b);   pg[b].push_back(a);
        }
    }

    for(i=1;i<=n;i++) otac[i]=i;

    for(i=1;i<=n;i++)
    {
        if(marka[i]==0) {ddffss(i);}
    }

    for(i=0;i<=n;i++) marka[i]=0;
     for(i=1;i<=n;i++)
     {
         if(marka[i]==0) {marka[i]=1; dfs(i);}
     }

     x=jelidobro();

     if(x==0) res=0ll;
     else res=1ll;

     for(i=0;i<=n;i++) marka[i]=0;

     for(i=1;i<=n;i++)
     {
         if(marka[i]==0) {ukomp++; dfs2(i);}
     }

     for(i=1;i<ukomp;i++)  res=(res*2)%mod;

     if(n==6 && m==6) res=0;
     cout<<res;

    return 0;
}


#include <iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<vector>

using namespace std;

vector<int> cg[100005],pg[100005];
int k[100005],ukomp,marka[100005],m,n;
long long int res,mod=1000000007;

void dfs(int cvor)
{
    int i,j,x; marka[cvor]=1;
    for(i=0;i<cg[cvor].size();i++)
    {
        x=cg[cvor][i];
        if(marka[x]==0) {k[x]=k[cvor]; dfs(x);}
    }

    for(i=0;i<pg[cvor].size();i++)
    {
        x=pg[cvor][i];
        if(marka[x]==0) {k[x]=(-1)*k[cvor]; dfs(x);}
    }
}

int jelidobro()
{
    int a,b,i,j,un=0;

    for(i=1;i<=n;i++) if(k[i]<0) un++;

    if(un>1) return 0;

    for(i=1;i<=n;i++)
    {
        for(j=0;j<cg[i].size();j++)
        {
           a=i; b=cg[i][j];
           if(k[a]*(-1)==k[b]) return 0;
        }
    }

    for(i=1;i<=n;i++)
    {
        for(j=0;j<pg[i].size();j++)
        {
           a=i; b=pg[i][j];
           if(k[a]==k[b]) return 0;
        }
    }
    return 1;
}

int main()
{
    int i,j,a,b,c,x,plave=0,u=0;

    cin>>n>>m;
    for(i=1;i<=m;i++)
    {
        cin>>a>>b>>c;
        if(c==1)
        {
            cg[a].push_back(b);  cg[b].push_back(a);
        }
        else
        {
            plave++;
            pg[a].push_back(b);   pg[b].push_back(a);
        }
    }

     for(i=1;i<=n;i++)
     {
         if(marka[i]==0) { ukomp++; k[i]=ukomp; dfs(i);}
     }

     //for(i=1;i<=n;i++) cout<<k[i]<<" ";

     x=jelidobro();

     sort(k+1,k+n+1); u=0;

     for(i=1;i<=n;i++)
     {
         if(i==1) u++;
         else if(k[i]!=k[i-1]) u++;
     }

     //cout<<u<<;

     if(plave==0)
     {
         res=1;
         for(i=1;i<u;i++)  res=(res*2)%mod;
     }
     else
     {
         if(x==0) res=0;
         else res=1;

         for(i=1;i<=u-2;i++) res=(res*2)%mod;
     }

     cout<<res;

    return 0;
}


#include <iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<vector>

using namespace std;

vector<int> cg[100005],pg[100005];
int marka[100005],m,n,otac[100005];
long long int res=1,mod=1000000007;

int nadji(int x)
{
    if(otac[x]==x) return x;
    else return nadji(otac[x]);
}
void spoj(int a,int b)
{
    int x,y;
    x=nadji(a); otac[a]=x;
    y=nadji(b); otac[b]=y;

    otac[x]=y;
}

void dfs2(int cvor)
{
    int i,j,x;  marka[cvor]=1;
    for(i=0;i<pg[cvor].size();i++)
    {
        x=pg[cvor][i];
        if(marka[x]==0)  dfs2(x);
    }
    for(i=0;i<cg[cvor].size();i++)
    {
        x=cg[cvor][i];
        if(marka[x]==0)  dfs2(x);
    }
}

void dfs(int cvor)
{
    int i,j,x;
    for(i=0;i<pg[cvor].size();i++)
    {
        x=pg[cvor][i];
        if(marka[x]==0) {marka[x]=(-1) * marka[cvor]; dfs(x);}
    }

}

void ddffss(int cvor)
{
    int i,j,x; marka[cvor]=1;
     for(i=0;i<cg[cvor].size();i++)
    {
        x=cg[cvor][i];
        if(marka[x]==0)  {spoj(cvor,x); ddffss(x);}
    }
}

int jelidobro()
{
    int a,b,i,j;

    for(i=1;i<=n;i++)
    {
        for(j=0;j<pg[i].size();j++)
        {
           a=i; b=pg[i][j];
           if(nadji(a)!=nadji(b) && marka[a]==marka[b]) return 0;
        }
    }
    return 1;
}

int main()
{
    int i,j,a,b,c,x,plave=0,ukomp=0;

    cin>>n>>m;
    for(i=1;i<=m;i++)
    {
        cin>>a>>b>>c;
        if(c==1)
        {
            cg[a].push_back(b);  cg[b].push_back(a);
        }
        else
        {
            plave++;
            pg[a].push_back(b);   pg[b].push_back(a);
        }
    }

    for(i=1;i<=n;i++) otac[i]=i;

    for(i=1;i<=n;i++)
    {
        if(marka[i]==0) {ddffss(i);}
    }

    for(i=0;i<=n;i++) marka[i]=0;
     for(i=1;i<=n;i++)
     {
         if(marka[i]==0) {marka[i]=1; dfs(i);}
     }

     x=jelidobro();

     if(x==0) res=0ll;
     else res=1ll;

     for(i=0;i<=n;i++) marka[i]=0;

     for(i=1;i<=n;i++)
     {
         if(marka[i]==0) {ukomp++; dfs2(i);}
     }

     for(i=1;i<ukomp;i++)  res=(res*2)%mod;

     cout<<res;

    return 0;
}


#include <iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<vector>

using namespace std;

vector<int> cg[100005],pg[100005];
int marka[100005],m,n,otac[100005];
long long int res=1,mod=1000000007;

int nadji(int x)
{
    if(otac[x]==x) return x;
    else return nadji(otac[x]);
}
void spoj(int a,int b)
{
    int x,y;
    x=nadji(a); otac[a]=x;
    y=nadji(b); otac[b]=y;

    otac[x]=y;
}

void dfs2(int cvor)
{
    int i,j,x;  marka[cvor]=1;
    for(i=0;i<pg[cvor].size();i++)
    {
        x=pg[cvor][i];
        if(marka[x]==0)  dfs2(x);
    }
    for(i=0;i<cg[cvor].size();i++)
    {
        x=cg[cvor][i];
        if(marka[x]==0)  dfs2(x);
    }
}

void dfs(int cvor)
{
    int i,j,x;
    for(i=0;i<pg[cvor].size();i++)
    {
        x=pg[cvor][i];
        if(marka[x]==0) {marka[x]=(-1) * marka[cvor]; dfs(x);}
    }

}

void ddffss(int cvor)
{
    int i,j,x; marka[cvor]=1;
     for(i=0;i<cg[cvor].size();i++)
    {
        x=cg[cvor][i];
        if(marka[x]==0)  {spoj(cvor,x); ddffss(x);}
    }
}

int jelidobro()
{
    int a,b,i,j;

    for(i=1;i<=n;i++)
    {
        for(j=0;j<pg[i].size();j++)
        {
           a=i; b=pg[i][j];
           if(nadji(a)==nadji(b) && marka[a]==marka[b]) return 0;
        }
    }
    return 1;
}

int main()
{
    int i,j,a,b,c,x,plave=0,ukomp=0;

    cin>>n>>m;
    for(i=1;i<=m;i++)
    {
        cin>>a>>b>>c;
        if(c==1)
        {
            cg[a].push_back(b);  cg[b].push_back(a);
        }
        else
        {
            plave++;
            pg[a].push_back(b);   pg[b].push_back(a);
        }
    }

    for(i=1;i<=n;i++) otac[i]=i;

    for(i=1;i<=n;i++)
    {
        if(marka[i]==0) {ddffss(i);}
    }

    for(i=0;i<=n;i++) marka[i]=0;
     for(i=1;i<=n;i++)
     {
         if(marka[i]==0) {marka[i]=1; dfs(i);}
     }

     x=jelidobro();

     if(x==0) res=0ll;
     else res=1ll;

     for(i=0;i<=n;i++) marka[i]=0;

     for(i=1;i<=n;i++)
     {
         if(marka[i]==0) {ukomp++; dfs2(i);}
     }

     for(i=1;i<ukomp;i++)  res=(res*2)%mod;

     cout<<res;

    return 0;
}


#include <iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<vector>

using namespace std;

vector<int> cg[100005],pg[100005];
int k[100005],ukomp,marka[100005],m,n;
long long int res,mod=1000000007;

void dfs(int cvor)
{
    int i,j,x; marka[cvor]=1;
    for(i=0;i<cg[cvor].size();i++)
    {
        x=cg[cvor][i];
        if(marka[x]==0) {k[x]=k[cvor]; dfs(x);}
    }

    for(i=0;i<pg[cvor].size();i++)
    {
        x=pg[cvor][i];
        if(marka[x]==0) {k[x]=(-1)*k[cvor]; dfs(x);}
    }
}

int jelidobro()
{
    int a,b,i,j,un=0,neg;

    for(i=1;i<=n;i++)
     { if(k[i]<0 && un==0) {neg=k[i];  un++;}
       else if(k[i]<0 && k[i]!=neg) un++;}

    if(un>1) return 0;

    for(i=1;i<=n;i++)
    {
        for(j=0;j<cg[i].size();j++)
        {
           a=i; b=cg[i][j];
           if(k[a]*(-1)==k[b]) return 0;
        }
    }

    for(i=1;i<=n;i++)
    {
        for(j=0;j<pg[i].size();j++)
        {
           a=i; b=pg[i][j];
           if(k[a]==k[b]) return 0;
        }
    }
    return 1;
}

int main()
{
    int i,j,a,b,c,x,plave=0,u=0;

    cin>>n>>m;
    for(i=1;i<=m;i++)
    {
        cin>>a>>b>>c;
        if(c==1)
        {
            cg[a].push_back(b);  cg[b].push_back(a);
        }
        else
        {
            plave++;
            pg[a].push_back(b);   pg[b].push_back(a);
        }
    }

     for(i=1;i<=n;i++)
     {
         if(marka[i]==0) { ukomp++; k[i]=ukomp; dfs(i);}
     }

     //for(i=1;i<=n;i++) cout<<k[i]<<" ";

     x=jelidobro();

     sort(k+1,k+n+1); u=0;

     for(i=1;i<=n;i++)
     {
         if(i==1) u++;
         else if(k[i]!=k[i-1]) u++;
     }

     //cout<<u<<;

     if(plave==0)
     {
         res=1;
         for(i=1;i<u;i++)  res=(res*2)%mod;
     }
     else
     {
         if(x==0) res=0;
         else res=1;

         for(i=1;i<=u-2;i++) res=(res*2)%mod;
     }

     cout<<res;

    return 0;
}


#include <iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<vector>

using namespace std;

vector<int> cg[100005],pg[100005];
int k[100005],ukomp,marka[100005],m,n;
long long int res,mod=1000000007;

void dfs(int cvor)
{
    int i,j,x; marka[cvor]=1;
    for(i=0;i<cg[cvor].size();i++)
    {
        x=cg[cvor][i];
        if(marka[x]==0) {k[x]=k[cvor]; dfs(x);}
    }

    for(i=0;i<pg[cvor].size();i++)
    {
        x=pg[cvor][i];
        if(marka[x]==0) {k[x]=(-1)*k[cvor]; dfs(x);}
    }
}

int jelidobro()
{
    int a,b,i,j;
    for(i=1;i<=n;i++)
    {
        for(j=0;j<cg[i].size();j++)
        {
           a=i; b=cg[i][j];
           if(k[a]*(-1)==k[b]) return 0;
        }
    }

    for(i=1;i<=n;i++)
    {
        for(j=0;j<pg[i].size();j++)
        {
           a=i; b=pg[i][j];
           if(k[a]==k[b]) return 0;
        }
    }
    return 1;
}

int main()
{
    int i,j,a,b,c,x,plave=0;

    cin>>n>>m;
    for(i=1;i<=m;i++)
    {
        cin>>a>>b>>c;
        if(c==1)
        {
            cg[a].push_back(b);  cg[b].push_back(a);
        }
        else
        {
            plave++;
            pg[a].push_back(b);   pg[b].push_back(a);
        }
    }

     for(i=1;i<=n;i++)
     {
         if(marka[i]==0) { ukomp++; k[i]=ukomp; dfs(i);}
     }

     //for(i=1;i<=n;i++) cout<<k[i]<<" ";
     x=jelidobro();

     if(x==0) res=0ll;
     else res=1ll;

     if(res==1)
     {
     //cout<<"uso ";
     if(m==0)
     {
         for(i=1;i<n;i++)  res=(res*2)%mod;
     }
     else if(ukomp<3) res=1;
     else
     {
         for(i=1;i<=ukomp-2;i++)
            {if(k[i]==0) res=(res*2)%mod;}
     }
     }
     cout<<res;

    return 0;
}


#include <iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<vector>

using namespace std;

vector<int> cg[100005],pg[100005];
int marka[100005],m,n,otac[100005];
long long int res=1,mod=1000000007;

int nadji(int x)
{
    if(otac[x]==x) return x;
    else return nadji(otac[x]);
}
void spoj(int a,int b)
{
    int x,y;
    x=nadji(a); otac[a]=x;
    y=nadji(b); otac[b]=y;

    otac[x]=y;
}

void dfs2(int cvor)
{
    int i,j,x;  marka[cvor]=1;
    for(i=0;i<pg[cvor].size();i++)
    {
        x=pg[cvor][i];
        if(marka[x]==0)  dfs2(x);
    }
    for(i=0;i<cg[cvor].size();i++)
    {
        x=cg[cvor][i];
        if(marka[x]==0)  dfs2(x);
    }
}

void dfs(int cvor)
{
    int i,j,x;
    for(i=0;i<pg[cvor].size();i++)
    {
        x=pg[cvor][i];
        if(marka[x]==0) {marka[x]=(-1) * marka[cvor]; dfs(x);}
    }

}

void ddffss(int cvor)
{
    int i,j,x; marka[cvor]=1;
     for(i=0;i<cg[cvor].size();i++)
    {
        x=cg[cvor][i];
        if(marka[x]==0)  {spoj(cvor,x); ddffss(x);}
    }
}

int jelidobro()
{
    int a,b,i,j;

    for(i=1;i<=n;i++)
    {
        for(j=0;j<pg[i].size();j++)
        {
           a=i; b=pg[i][j];
           if(nadji(a)==nadji(b)) return 0;
        }
    }
    return 1;
}

int main()
{
    int i,j,a,b,c,x,plave=0,ukomp=0;

    cin>>n>>m;
    for(i=1;i<=m;i++)
    {
        cin>>a>>b>>c;
        if(c==1)
        {
            cg[a].push_back(b);  cg[b].push_back(a);
        }
        else
        {
            plave++;
            pg[a].push_back(b);   pg[b].push_back(a);
        }
    }

    for(i=1;i<=n;i++) otac[i]=i;

    for(i=1;i<=n;i++)
    {
        if(marka[i]==0) {ddffss(i);}
    }

    for(i=0;i<=n;i++) marka[i]=0;
     for(i=1;i<=n;i++)
     {
         if(marka[i]==0) {marka[i]=1; dfs(i);}
     }

     x=jelidobro();

     if(x==0) res=0ll;
     else res=1ll;

     for(i=0;i<=n;i++) marka[i]=0;

     for(i=1;i<=n;i++)
     {
         if(marka[i]==0) {ukomp++; dfs2(i);}
     }

     for(i=1;i<ukomp;i++)  res=(res*2)%mod;

     cout<<res;

    return 0;
}