题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=648&page=show_problem&problem=5150
题目大意:给一幅N个点M条边的无向图,有一些边,其中一部分只能涂红色,一部分只能涂黑色,一部分两种颜色都可以涂。现要求红色的边不超过K条的生成树个数模1e9+7的值。
思路:感谢昂神滋磁,贴链接:http://sd-invol.github.io/2015/05/31/Matrix-Tree-Polynomial/
由于不会范德蒙德矩阵,也不会拉格朗日插值,只好乖乖高斯消元了……
代码(0.429S):
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 #include <iostream> 5 #include <vector> 6 using namespace std; 7 typedef long long LL; 8 typedef vector<vector<int> > Mat; 9 10 const int MAXV = 55; 11 const int MAXE = MAXV * MAXV; 12 const int MOD = 1e9 + 7; 13 14 void debug(const Mat &a) { 15 puts("#debug:"); 16 for(auto &i : a) { 17 for(auto j : i) printf("%d ", j); 18 puts(""); 19 } 20 } 21 22 int inv(int x) { 23 if(x == 1) return 1; 24 return LL(MOD - MOD / x) * inv(MOD % x) % MOD; 25 } 26 27 int det(Mat &a, int n) { 28 LL res = 1; 29 for(int i = 1; i < n; ++i) { 30 if(a[i][i] == 0) return 0; 31 for(int j = i + 1; j < n; ++j) { 32 LL t = LL(a[j][i]) * inv(a[i][i]) % MOD; 33 for(int k = i; k < n; ++k) { 34 a[j][k] -= (a[i][k] * t) % MOD; 35 if(a[j][k] < 0) a[j][k] += MOD; 36 } 37 } 38 res = (res * a[i][i]) % MOD; 39 } 40 return res; 41 } 42 43 void guass(Mat &a, int n) { 44 for(int i = 0; i < n; ++i) { 45 for(int j = i + 1; j < n; ++j) { 46 LL t = LL(a[j][i]) * inv(a[i][i]) % MOD; 47 for(int k = i; k <= n; ++k) { 48 a[j][k] -= (a[i][k] * t) % MOD; 49 if(a[j][k] < 0) a[j][k] += MOD; 50 } 51 } 52 } 53 for(int i = n - 1; i >= 0; --i) { 54 for(int j = i + 1; j < n; ++j) { 55 a[i][n] -= (LL(a[i][j]) * a[j][n]) % MOD; 56 if(a[i][n] < 0) a[i][n] += MOD; 57 } 58 a[i][n] = LL(a[i][n]) * inv(a[i][i]) % MOD; 59 } 60 } 61 62 int la[MAXE], lb[MAXE], kind[MAXE]; 63 int T, n, m, k; 64 65 int get_column(int a) { 66 Mat mat(n, vector<int>(n)); 67 for(int i = 0; i < m; ++i) { 68 int t = (kind[i] & 1) * a + (kind[i] >> 1); 69 mat[la[i]][la[i]] += t; 70 mat[lb[i]][lb[i]] += t; 71 mat[la[i]][lb[i]] = mat[lb[i]][la[i]] = (t > 0 ? MOD - t : 0); 72 } 73 return det(mat, n); 74 } 75 76 int solve() { 77 Mat mat(n, vector<int>(n + 1)); 78 for(int i = 0; i < n; ++i) { 79 LL tmp = 1; 80 for(int j = 0; j < n; ++j) 81 mat[i][j] = tmp, tmp = (tmp * i) % MOD; 82 mat[i][n] = get_column(i); 83 } 84 //debug(mat); 85 guass(mat, n); 86 87 int res = 0; 88 for(int i = 0; i <= k; ++i) { 89 res += mat[i][n]; 90 if(res >= MOD) res -= MOD; 91 } 92 return res; 93 } 94 95 int main() { 96 scanf("%d", &T); 97 for(int t = 1; t <= T; ++t) { 98 scanf("%d%d%d", &n, &m, &k); 99 for(int i = 0; i < m; ++i) { 100 scanf("%d%d%d", &la[i], &lb[i], &kind[i]); 101 la[i]--, lb[i]--; 102 } 103 printf("Case #%d: %d\n", t, solve()); 104 } 105 }