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;


const int mod = 1000000009;
struct Mod {
public:
	int num;
	Mod() : Mod(0) { ; }
	Mod(long long int n) : num((n % mod + mod) % mod) {
		static_assert(mod<INT_MAX / 2, "mod is too big, please make num 'long long int' from 'int'");
	}
	Mod(int n) : Mod(static_cast<long long int>(n)) { ; }
	operator int() { return num; }
};

Mod operator+(const Mod a, const Mod b) { return Mod((a.num + b.num) % mod); }
Mod operator+(const long long int a, const Mod b) { return Mod(a) + b; }
Mod operator+(const Mod a, const long long int  b) { return b + a; }
Mod operator++(Mod &a) { return a + Mod(1); }
Mod operator-(const Mod a, const Mod b) { return Mod((mod + a.num - b.num) % mod); }
Mod operator-(const long long int a, const Mod b) { return Mod(a) - b; }
Mod operator--(Mod &a) { return a - Mod(1); }
Mod operator*(const Mod a, const Mod b) { return Mod(((long long)a.num * b.num) % mod); }
Mod operator*(const long long int a, const Mod b) { return Mod(a)*b; }
Mod operator*(const Mod a, const long long int b) { return Mod(b)*a; }
Mod operator*(const Mod a, const int b) { return Mod(b)*a; }
Mod operator+=(Mod &a, const Mod b) { return a = a + b; }
Mod operator+=(long long int &a, const Mod b) { return a = a + b; }
Mod operator-=(Mod &a, const Mod b) { return a = a - b; }
Mod operator-=(long long int &a, const Mod b) { return a = a - b; }
Mod operator*=(Mod &a, const Mod b) { return a = a * b; }
Mod operator*=(long long int &a, const Mod b) { return a = a * b; }
Mod operator*=(Mod& a, const long long int &b) { return a = a * b; }
Mod operator^(const Mod a, const int n) {
	if (n == 0) return Mod(1);
	Mod res = (a * a) ^ (n / 2);
	if (n % 2) res = res * a;
	return res;
}
Mod mod_pow(const Mod a, const int n) {
	if (n == 0) return Mod(1);
	Mod res = mod_pow((a * a), (n / 2));
	if (n % 2) res = res * a;
	return res;
}
Mod inv(const Mod a) { return a ^ (mod - 2); }
Mod operator/(const Mod a, const Mod b) {
	assert(b.num != 0);
	return a * inv(b);
}
Mod operator/(const long long int a, const Mod b) {
	return Mod(a) / b;
}
Mod operator/=(Mod &a, const Mod b) {
	return a = a / b;
}

#define MAX_MOD_N 1024000

Mod fact[MAX_MOD_N], factinv[MAX_MOD_N];
void init() {
	fact[0] = Mod(1); factinv[0] = 1;
	for (int i = 0; i < MAX_MOD_N - 1; ++i) {
		fact[i + 1] = fact[i] * Mod(i + 1);
		factinv[i + 1] = factinv[i] / Mod(i + 1);
	}
}
Mod comb(const int a, const int b) {
	while(a < b) {
		cout << 1 << endl;

	}
	while (b < 0 || a < 0) {
		cout << 1 << endl;

	}
	return fact[a] * factinv[b] * factinv[a - b];
}

struct rel {
	int a;
	int b;
	int love;
};
bool operator== (const rel&l, const rel&r) {
	return l.a == r.a&&l.b == r.b&&l.love == r.love;
}

struct UnionFind {
	vector<int> data;
	UnionFind(int size) : data(size, -1) { }
	bool unionSet(int x, int y) {
		x = root(x); y = root(y);
		if (x != y) {
			if (data[y] < data[x]) swap(x, y);
			data[x] += data[y]; data[y] = x;
		}
		return x != y;
	}
	bool findSet(int x, int y) {
		return root(x) == root(y);
	}
	int root(int x) {
		return data[x] < 0 ? x : data[x] = root(data[x]);
	}
	int size(int x) {
		return -data[root(x)];
	}
};
vector<Mod>dp(1e6 + 1);
Mod getrest(const int rest) {
	if (rest < 0) {
		return 0;
	}
	else {
		if (rest % 3) {
			assert(false);
			return 0;
		}
		else {
			return dp[rest/3];
		}
	}
}
int N, M;
Mod getans(const map<int,int>&mp) {
	vector<int>v;

	Mod ans = 1;
	for (auto m : mp) {
		if (m.second >= 4)return 0;
		else if(m.second==1){
		}
		else {
			v.emplace_back(m.second);
		}
	}
	 int rest = 3 * N - accumulate(v.begin(), v.end(),0);
	if (N < v.size())return 0;
	for (auto n : v) {
		if (n == 2) {
		ans *= rest;
		}
		else {
			assert(n == 3);
			ans *= 1;
		}
		//if (rest < 3 - n) {
		//	//cout << 1 << endl;
		//	return 0;
		//}
		
		//ans *= comb(rest, 3 - n);
		
		rest -= (3-n);
	}
	ans *= getrest(rest);
	return ans;
}
int main() {
	dp[0] = 1;
	for (int i = 1; i <= 100000; ++i) {
		dp[i] = dp[i - 1] * Mod(3*i - 1)*Mod(3*i - 2) / Mod(2);
	}
	init();cin >> N >> M;
	vector<rel>rels;
	vector<rel>hates;
	set<int>aset;
	for (int i = 0; i < M; ++i) {
		int a, b, c; cin >> a >> b >> c;
		c = !c;
		a--; b--;
		aset.emplace(a);
		aset.emplace(b);
		rels.push_back(rel{ a,b,c });
		if (find(rels.begin(), rels.end(), rel{ b,a,c }) != rels.end()) {
			//cout << "a" << endl;
			return 0;
		}
		if (find(rels.begin(), rels.end(), rel{ b,a,!c }) != rels.end()) {
			//cout << "a" << endl;
			return 0;
		}
	}
	map<int, int>mp;
	int n = 0;
	for (auto s : aset) {
		mp[s] = n;
		n++;
	}
	for (auto&r : rels) {
		r.a = mp[r.a];
		r.b = mp[r.b];
	}
	UnionFind uf(aset.size());
	for (int i = 0; i < M; ++i) {
		if (rels[i].love) {
			uf.unionSet(rels[i].a, rels[i].b);
		}
		else {
			hates.emplace_back(rels[i]);
		}
	}
	assert(hates.size() <= 18);
	Mod ans = 0;
	for (int i = 0; i < (1<<hates.size()); ++i) {
		UnionFind nowuf(uf);
		bitset<18>bs(i);
		for (int j = 0; j < hates.size(); ++j) {
			
			if (bs[j]) {
				nowuf.unionSet(hates[j].a, hates[j].b);
			}
		}
		map<int, int>lovemp;
		for (int j = 0; j < aset.size(); ++j) {
			lovemp[nowuf.root(j)]++;
		}
		if (bs.count() % 2) {
			ans -= getans(lovemp);
		}
		else {
			ans += getans(lovemp);
		}
	}
	cout << ans << endl;
	return 0;
}