JAG2015 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  N  10
6
) and M
(1  M  18). The i-th line of the following M lines contains three integers Ai
, Bi
(1  Ai
; Bi  3N,
Ai , Bi
), and Ci (Ci 2 f0; 1g). Ai
and Bi
denote indices of the students and Ci
denotes the relation type.
If Ci
is 0, the Ai
-th student and the Bi -th student have a good relation. If Ci
is 1, they have a bad relation.
You can assume that fAi
; Bi g , fA j
; B j g if i , j for all 1  i; j  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

#include <bits/stdc++.h>
 
#define long long long
#define LOOPVAR_TYPE long
 
#define all(x) (x).begin(), (x).end()
#define max(x, y) ((x) > (y) ? (x) : (y))
#define min(x, y) ((x) < (y) ? (x) : (y))
#define sz(x) ((LOOPVAR_TYPE)(x).size())
#define foreach(it, X) for(__typeof((X).begin()) it = (X).begin(); it != (X).end(); it++)
#define GET_MACRO(_1, _2, _3, NAME, ...) NAME
#define _rep(i, n) _rep2(i, 0, n)
#define _rep2(i, a, b) for(LOOPVAR_TYPE i = (LOOPVAR_TYPE)(a); i < (LOOPVAR_TYPE)(b); i++)
#define rep(...) GET_MACRO(__VA_ARGS__, _rep2, _rep)(__VA_ARGS__)
 
#define fir first
#define sec second
#define mp make_pair
#define mt make_tuple
#define pb push_back
 
const double EPS = 1e-9;
const double PI = acos(-1.0);
const long INF = 1070000000LL;
const long MOD = 1000000009LL;
 
using namespace std;
 
typedef istringstream iss;
typedef stringstream sst;
typedef pair<LOOPVAR_TYPE, LOOPVAR_TYPE> pi;
typedef vector<LOOPVAR_TYPE> vi;
 
//
int par_uf[1000010],rank_uf[1000010];
 
void init(int n){for(int i=0;i<n;i++){par_uf[i]=i;rank_uf[i]=0;}}
int find(int x){if(par_uf[x]==x)return x;else return par_uf[x]=find(par_uf[x]);}
void unite(int x,int y){x=find(x);y=find(y);if(x==y)return;if(rank_uf[x]<rank_uf[y])par_uf[x]=y;else{par_uf[y]=x;if(rank_uf[x]==rank_uf[y])rank_uf[x]++;}}
bool same(int x,int y){return find(x)==find(y);}
//
 
int N, M;
int M0,a0[20],b0[20],c0[20];
int M1,a1[20],b1[20],c1[20];
int conv[3000010];
long way3[1000010];
 
int main(){
	cin.tie(0);
	ios_base::sync_with_stdio(0);
	
	cin>>N>>M;
	memset(conv,-1,sizeof(conv));
	int cur = 0;
	rep(i,M){
		int a,b,c;
		cin>>a>>b>>c;
		a--; b--;
		if(c == 1) a0[M0] = a, b0[M0] = b, c0[M0] = c, M0++;
		else a1[M1] = a, b1[M1] = b, c1[M1] = c, M1++;
		if(conv[a] == -1){
			conv[a] = cur++;
		}
		if(conv[b] == -1){
			conv[b] = cur++;
		}
	}
	way3[0] = 1;
	rep(i,N){
		way3[i+1] = way3[i] * (3*i+2) % MOD * (3*i+1) % MOD * 500000005 % MOD;
	}
	long ans = 0;
	rep(mask, 1<<M0){
		init(cur);
		rep(i,M0){
			if(mask >> i & 1){
				unite(conv[a0[i]], conv[b0[i]]);
			}
		}
		rep(i,M1){
			unite(conv[a1[i]], conv[b1[i]]);
		}
		int g[36] = {};
		rep(i,cur){
			g[find(i)]++;
		}
		int fail = 0;
		int rest = 3*N;
		int two = 0;
		rep(i,cur){
			if(g[i] > 3){
				fail = 1;
				break;
			}
			if(g[i] == 3){
				rest -= 3;
			}
			if(g[i] == 2){
				rest -= 2;
				two++;
			}
		}
		if(fail)continue;
		long way = way3[(rest - two)/3];
		rep(i,two){
			way = way * (rest - i) % MOD;
		}
		ans += __builtin_popcount(mask) % 2 ? MOD - way : way;
	}
	ans %= MOD;
	cout<<ans<<endl;
}


你可能感兴趣的:(JAG2015 ICPC Teams)