记录编号 143235 评测结果 AAAAAAAAAA
题目名称 [JSOI 2008] 最小生成树计数 最终得分 100
用户昵称 GravatarAsm.Def 是否通过 通过
代码语言 C++ 运行时间 0.008 s
提交时间 2014-12-13 13:27:25 内存使用 0.26 MiB
显示代码纯文本
#include <cctype>
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <assert.h>
using namespace std;
template<typename T>inline void getd(T &x){
	char c = getchar(); bool minus = 0;
	while(!isdigit(c) && c != '-')c = getchar();
	if(c == '-')minus = 1, c = getchar();
	x = c - '0';
	while(isdigit(c = getchar()))x = x * 10 + c - '0';
	if(minus)x = -x;
}
/*========================================================*/
const int maxn = 103, maxm = 1003, mod = 31011;
typedef pair<int, pair<int, int> > Edge;
Edge E[maxm];
#define val first
#define u second.first
#define v second.second
int N, M, Ans = 1, *Mat[22], sum;

inline void watch();

struct UFS{
	int pre[maxn];
	void init(int x){for(int i = 0;i <= x;++i)pre[i] = i;}
	int find(int x){return pre[x] == x ? x : pre[x] = find(pre[x]);}
	void link(int a, int b){pre[find(a)] = find(b);}
}ufs, tmpS;
inline void init(){
	getd(N), getd(M);
	int i;
	ufs.init(N);
	for(i = 0;i < M;++i)
		getd(E[i].u), getd(E[i].v), getd(E[i].val);
	for(i = 0;i < 21;++i)
		Mat[i] = new int[22];
	sort(E, E + M);
	sum = N;
}

inline int det(int n){
	int i, j, k, t, ans = 1;
	for(i = 1;i < n;++i){
		for(j = i + 1;j < n;++j){
			while(Mat[j][i]){
				t = Mat[i][i] / Mat[j][i];
				if(t)
					for(k = i;k < n;++k)
						Mat[i][k] = (Mat[i][k] - Mat[j][k] * t) % mod;
				
				swap(Mat[i], Mat[j]), ans = -ans;
			}
		}
		ans = ans * Mat[i][i] % mod;
	}
	return ans;
}
int tmp[22], block[22], cnt;
inline void watch(){
	/*int i, j;
	for(i = 0;i < cnt;++i){
		for(j = 0;j < cnt;++j)
			printf("%5d ", Mat[i][j]);
		printf("\n\n");
	}
	printf("\n\n\n");*/
}
#define index(x) ( lower_bound(block, block + cnt, x) - block )
inline void calc(Edge *A, int len){
	int i, j;
	//int t, adj[22];
	cnt = 1;
	for(i = 0,j = 0;i < len;++i){
		A[i].u = ufs.find(A[i].u);
		A[i].v = ufs.find(A[i].v);
		if(A[i].u == A[i].v)continue;
		tmp[j++] = A[i].u;
		tmp[j++] = A[i].v;
	}
	sort(tmp, tmp + j);
	block[0] = tmp[0];
	for(i = 1;i < j;++i)
		if(tmp[i] != block[cnt-1])block[cnt++] = tmp[i];
	
	for(i = 0;i < cnt;++i)for(j = 0;j < cnt;++j)
		Mat[i][j] = 0;
	
	tmpS.init(cnt);
	
	for(i = 0;i < len;++i){
		if(A[i].u == A[i].v)continue;
		if(ufs.find(A[i].u) != ufs.find(A[i].v))--sum;
		ufs.link(A[i].u, A[i].v);
		A[i].u = index(A[i].u);
		A[i].v = index(A[i].v);
		++Mat[A[i].u][A[i].u];
		++Mat[A[i].v][A[i].v];
		//adj[A[i].u] |= (1 << A[i].v);
		//adj[A[i].v] |= (1 << A[i].u);
		--Mat[A[i].u][A[i].v];
		--Mat[A[i].v][A[i].u];
		tmpS.link(A[i].u, A[i].v);
	}
	int a, b;
	for(i = 1;i < cnt;++i)
		if((a = tmpS.find(i)) != (b = tmpS.find(i-1))){
			++Mat[a][a], ++Mat[b][b];
			//adj[a] |= (1 << b);
			//adj[b] |= (1 << a);
			--Mat[a][b], --Mat[b][a];
			tmpS.link(a, b);
		}
	
	Ans = Ans * det(cnt) % mod;
}
inline void work(){
	int i = 0, j = 1, t;
	while(i < M){
		while(j < M && E[i].val == E[j].val)++j;
		if((t = j - i) > 1)calc(E + i, j - i);
		else if(ufs.find(E[i].u) != ufs.find(E[i].v))
			ufs.link(E[i].u, E[i].v), --sum;
		i = j++;
	}
	if(sum > 1)printf("0\n");
	else 
		printf("%d\n", Ans);
}
int main(){
	#if defined DEBUG
	freopen("test", "r", stdin);
	#else
	freopen("bzoj_1016.in", "r", stdin);
	freopen("bzoj_1016.out", "w", stdout);
	#endif
	init();
	work();
	
	return 0;
}