首页 > 技术文章 > UVALive 7138 The Matrix Revolutions(Matrix-Tree + 高斯消元)(2014 Asia Shanghai Regional Contest)

oyking 2015-06-24 20:42 原文

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

 

推荐阅读