UVALive 7138 The Matrix Revolutions(Matrix-Tree + 高斯消元)(2014 Asia Shanghai Regional Contest)

题目链接: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 }
View Code

 

你可能感兴趣的:(Matrix)