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++14 (judge verdict: Accepted)

#include <bits/stdc++.h>
#define syosu(x) fixed<<setprecision(x)
using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair<int,int> P;
typedef pair<double,double> pdd;
typedef pair<ll,ll> pll;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<string> vs;
typedef vector<P> vp;
typedef vector<vp> vvp;
typedef vector<pll> vpll;
typedef pair<int,P> pip;
typedef vector<pip> vip;
const int inf=1<<30;
const ll INF=1ll<<60;
const double pi=acos(-1);
const double eps=1e-8;
const ll mod=1e9+9;
const int dx[4]={-1,0,1,0},dy[4]={0,-1,0,1};

ll Pow(ll n,ll p){
	ll r=1;
	for(;p>0;p>>=1){
		if(p&1) r=(r*n)%mod;
		n=(n*n)%mod;
	}
	return r;
}

const int M=3000005;
ll F[M];

void Init(){
	F[0]=1;
	for(int i=1;i<M;i++) F[i]=F[i-1]*i%mod;
}

ll Div(ll n,ll m){
	return n*Pow(m,mod-2)%mod;
}

ll nCk(ll n,ll k){
	return Div(F[n],F[n-k]*F[k]%mod);
}

int n,m;
vi a,b;
vi c,d;

int main(){
	Init();
	cin>>n>>m;
	for(int i=0;i<m;i++){
		int u,v,w;
		cin>>u>>v>>w;
		if(w==0){
			a.push_back(u);
			b.push_back(v);
		}
		else{
			c.push_back(u);
			d.push_back(v);
		}
	}
	int sa=a.size(),sc=c.size();
	ll res=0;
	for(int i=0;i<1<<sc;i++){
		vi s=a,t=b,e;
		int tmp=0;
		for(int j=0;j<sc;j++) if(i&1<<j){
			s.push_back(c[j]);
			t.push_back(d[j]);
			tmp++;
		}
		m=s.size();
		for(int j=0;j<m;j++){
			e.push_back(s[j]);
			e.push_back(t[j]);
		}
		sort(e.begin(),e.end());
		e.erase(unique(e.begin(),e.end()),e.end());
		map<int,int> mp;
		int N=e.size();
		for(int j=0;j<N;j++) mp[e[j]]=j;
		vvi g(N);
		for(int j=0;j<m;j++){
			int u=mp[s[j]],v=mp[t[j]];
			g[u].push_back(v);
			g[v].push_back(u);
		}
		vi used(N);
		int x=3*n-N,y=0,z=0;
		bool B=0;
		for(int i=0;i<N;i++) if(!used[i]){
			int t=0;
			queue<int> q;
			q.push(i);
			used[i]++;
			int cnt=0;
			while(!q.empty()){
				int v=q.front();q.pop();
				cnt++;
				for(auto u:g[v]) if(!used[u]){
					used[u]++;
					q.push(u);
				}
			}
			if(cnt>3) B=1;
			if(cnt==2) y++;
			if(cnt==3) z++;
		}
		if(B||y>x) continue;
		ll ei=nCk(x,y)*F[y]%mod*Div(F[x-y],Pow(6,(x-y)/3)*F[(x-y)/3]%mod)%mod;
		if(tmp%2==1) (ei*=mod-1)%=mod;
		(res+=ei)%=mod;
	}
	cout<<res<<endl;
}