Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

Problem F
ICPC Teams

You are a coach of the International Collegiate Programming Contest (ICPC) club in your university. There are 3N students in the ICPC club and you want to make $N$ teams for the next ICPC. All teams in ICPC consist of 3 members. Every student belongs to exactly one team.

When you form the teams, you should consider several relationships among the students. Some student has an extremely good relationship with other students. If they belong to a same team, their performance will improve surprisingly. The contrary situation also occurs for a student pair with a bad relationship. In short, students with a good relationship must be in the same team, and students with a bad relationship must be in different teams. Since you are a competent coach, you know all $M$ relationships among the students.

Your task is to write a program that calculates the number of possible team assignments. Two assignments are considered different if and only if there exists a pair of students such that in one assignment they are in the same team and in the other they are not.

Input

The input consists of a single test case. The first line contains two integers $N$ $(1 \leq N \leq 10^6)$ and $M$ $(1 \leq M \leq 18)$. The $i$-th line of the following $M$ lines contains three integers $A_i$, $B_i$ $(1 \leq A_i, B_i \leq 3N, A_i \ne B_i)$, and $C_i$ $(C_i \in \{0, 1\})$. $A_i$ and $B_i$ denote indices of the students and $C_i$ denotes the relation type. If $C_i$ is 0, the $A_i$-th student and the $B_i$-th student have a good relation. If $C_i$ is 1, they have a bad relation. You can assume that $\{A_i, B_i\} \ne \{A_j, B_j\}$ if $i \ne j$ for all $1 \leq i, j \leq M$.

Output

Display a line containing the number of the possible team assignments modulo $10^9 + 9$.

Sample Input 1

2 2
1 2 0
3 4 1

Output for the Sample Input 1

2

Solution in C++11 (judge verdict: Wrong Answer)

#include<bits/stdc++.h>
using namespace std;

#define int long long
typedef vector<int>vint;
typedef pair<int,int>pint;
typedef vector<pint>vpint;
#define rep(i,n) for(int i=0;i<(n);i++)
#define reps(i,f,n) for(int i=(f);i<(n);i++)
#define all(v) (v).begin(),(v).end()
#define each(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
#define pb push_back
#define fi first
#define se second
template<typename A,typename B>inline void chmin(A &a,B b){if(a>b)a=b;}
template<typename A,typename B>inline void chmax(A &a,B b){if(a<b)a=b;}

const int mod=1000000009;
int mpow(int n,int m){
    int ret=1;
    while(m){
        if(m&1)ret=ret*n%mod;
        n=n*n%mod;
        m>>=1;
    }
    return ret;
}

int N,M;
int fact[3333333];
int inv[3333333];

int C(int n,int k){
    return fact[n]*inv[k]%mod*inv[n-k]%mod;
}

struct UnionFindTree{
    vector<int>par,sz;
    UnionFindTree(int n){
        par.resize(n);
        sz.resize(n);
        for(int i=0;i<n;i++){
            par[i]=i;
            sz[i]=1;
        }
    }
    int find(int x){
        return x==par[x]?x:par[x]=find(par[x]);
    }
    void unite(int x,int y){
        x=find(x);y=find(y);
        if(x==y)return;
        if(sz[x]<sz[y])swap(x,y);
        sz[x]+=sz[y];
        par[y]=x;
    }
    bool areSame(int x,int y){
        return find(x)==find(y);
    }
    int size(int x){
        return sz[find(x)];
    }
};

int table[3333333];

int calc(vpint A){
    vint xs;
    rep(i,A.size()){
        xs.pb(A[i].fi);
        xs.pb(A[i].se);
    }
    sort(all(xs));xs.erase(unique(all(xs)),xs.end());
    rep(i,A.size()){
        A[i].fi=lower_bound(all(xs),A[i].fi)-xs.begin();
        A[i].se=lower_bound(all(xs),A[i].se)-xs.begin();
    }

    UnionFindTree uf(xs.size());
    rep(i,A.size())uf.unite(A[i].fi,A[i].se);

    int cnt=0;
    rep(i,xs.size()){
        if(uf.find(i)!=i)continue;
        if(uf.sz[i]>3)return 0;
        if(uf.sz[i]==3)continue;
        cnt++;
    }

    int n=3*N-xs.size();
    int ret=fact[n]*inv[n-cnt]%mod;
    assert((n-cnt)%3==0);
    return ret*table[n-cnt]%mod;
}

signed main(){
    fact[0]=1;
    for(int i=1;i<3333333;i++)fact[i]=fact[i-1]*i%mod;
    inv[3333333-1]=mpow(fact[3333333-1],mod-2);
    for(int i=3333333-2;i>=0;i--)inv[i]=inv[i+1]*(i+1)%mod;
    table[0]=1;
    for(int i=3;i<3333333;i+=3){
        table[i]=table[i-3]*C(i-1,2)%mod;
    }

    cin>>N>>M;

    vpint A,B;
    rep(i,M){
        int a,b,c;
        cin>>a>>b>>c;
        a--;b--;
        if(c==0)A.pb({a,b});
        else B.pb({a,b});
    }

    int ans=0;

    for(int i=1;i<(1<<B.size());i++){
        vpint AA=A;
        rep(j,B.size())if(i>>j&1)AA.pb(B[j]);

        if(__builtin_popcount(i)%2==1)ans+=calc(AA);
        else ans-=calc(AA);
    }

    cout<<calc(A)-ans<<endl;
    return 0;
}