• 基尔霍夫矩阵题目泛做(AD第二轮)


    题目1: SPOJ 2832

    题目大意:

    求一个矩阵行列式模一个数P后的值。p不一定是质数。

    算法讨论:

    因为有除法而且p不一定是质数,不一定有逆元,所以我们用辗转相除法。

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <algorithm>
     6 
     7 using namespace std;
     8 
     9 const int N = 205;
    10 typedef long long ll;
    11 
    12 int n;
    13 ll p, mat[N][N];
    14 
    15 ll det(ll a[N][N]) {
    16   ll res = 1;
    17 
    18   for(int i = 1; i <= n; ++ i) {
    19     for(int j = i + 1; j <= n; ++ j) {
    20       while(a[j][i]) {
    21         ll t = a[i][i] / a[j][i];
    22 
    23         for(int k = i; k <= n; ++ k)
    24           a[i][k] = (a[i][k] - a[j][k] * t) % p;
    25         for(int k = i; k <= n; ++ k)
    26           swap(a[i][k], a[j][k]);
    27         res = -res;
    28       }
    29     }
    30     if(a[i][i] == 0) return 0;
    31     res = 1LL * res * a[i][i] % p;
    32   }
    33   return (res + p)  % p;
    34 }
    35 
    36 int main() {
    37   while(~scanf("%d%lld", &n, &p)) {
    38     for(int i = 1; i <= n; ++ i) {
    39       for(int j = 1; j <= n; ++ j) {
    40         scanf("%lld", &mat[i][j]);
    41         mat[i][j] %= p;
    42       }
    43     }
    44     printf("%lld
    ", det(mat));
    45   }
    46   return 0;
    47 }
    SPOJ 2832

    题目2: BZOJ 1002 轮状病毒

    题目大意:

    一棵有规律的树,求其生成树的数量。基尔霍夫矩裸上。

    关于矩阵树定理,有一个递推式: f[n] = 3 * f[n - 1] - f[n - 2] + 2;

    高精度一下即可。

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <cstdlib>
      4 #include <algorithm>
      5 #include <iostream>
      6  
      7 using namespace std;
      8  
      9 const int rad = 10;
     10  
     11 int n;
     12  
     13 struct BigInt {
     14   int v[1005];
     15   int len;
     16  
     17   BigInt() {
     18     memset(v, 0, sizeof v);
     19     len = 0;
     20   }
     21  
     22   friend BigInt operator + (BigInt a, BigInt b) {
     23     int tmp = max(a.len, b.len);
     24  
     25     for(int i = 1; i <= tmp; ++ i) {
     26       a.v[i] += b.v[i];
     27       if(a.v[i] >= rad) {
     28         a.v[i + 1] += a.v[i] / rad;
     29         a.v[i] %= rad;
     30       }
     31     }
     32     while(a.v[tmp + 1]) tmp ++;
     33     a.len = tmp;
     34  
     35     return a;
     36   }
     37  
     38   friend BigInt operator * (BigInt a, BigInt b) {
     39     BigInt c;
     40     int tmp = a.len + b.len;
     41  
     42     for(int i = 1; i <= a.len; ++ i) {
     43       for(int j = 1; j <= b.len; ++ j) {
     44         c.v[i + j - 1] += a.v[i] * b.v[j];
     45       }
     46     }
     47     for(int i = 1; i <= tmp; ++ i) {
     48       if(c.v[i] >= rad) {
     49         c.v[i + 1] += c.v[i] / rad;
     50         c.v[i] %= rad;
     51       }
     52       if(c.v[i]) c.len = i;
     53     }
     54  
     55     return c;
     56   }
     57  
     58   friend BigInt operator * (BigInt a, int k) {
     59     for(int i = 1; i <= a.len; ++ i) {
     60       a.v[i] *= k;
     61     }
     62     for(int i = 1; i <= a.len; ++ i) {
     63       a.v[i + 1] += a.v[i] / rad;
     64       a.v[i] %= rad;
     65     }
     66     if(a.v[a.len + 1]) a.len ++;
     67     return a;
     68   }
     69  
     70   friend BigInt operator - (BigInt a, BigInt b) {
     71     for(int i = 1; i <= a.len; ++ i) {
     72       a.v[i] -= b.v[i];
     73       if(a.v[i] < 0) {
     74         a.v[i + 1] -= 1;
     75         a.v[i] += rad;
     76       }
     77     }
     78     while(a.v[a.len] == 0)a.len --;
     79     return a;
     80   }
     81   void getint(int k) {
     82     while(k) {
     83       v[++ len] = k % 10;
     84       k /= 10;
     85     }
     86   }
     87    
     88   void print() {
     89     for(int i = len; i >= 1; -- i) {
     90       printf("%d", v[i]);
     91     }
     92   }
     93 }f[105], cst;
     94  
     95 void Input() {
     96   scanf("%d", &n);
     97 }
     98  
     99 void Solve() {
    100   f[1].getint(1);
    101   f[2].getint(5);
    102   cst.getint(2);
    103   for(int i = 3; i <= n; ++ i) {
    104     f[i] = f[i - 1] * 3 - f[i - 2] + cst;
    105   }
    106 }
    107  
    108 void Output() {
    109   f[n].print();
    110 }
    111  
    112 int main() {
    113   Input();
    114   Solve();
    115   Output();
    116  
    117   return 0;
    118 }
    BZOJ 1002

    题目3: SPOJ 104 HighWays

    题目大意:

    给一张图,求其生成树的个数。

    算法讨论:裸上基尔霍夫。

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <cstring>
     4 #include <cstdlib>
     5 #include <algorithm>
     6  
     7 using namespace std;
     8  
     9 typedef long long ll;
    10 const int N = 15;
    11  
    12 ll ans;
    13 int n, m;
    14 ll degree[N][N], G[N][N], self[N][N];
    15  
    16 ll det(ll a[N][N]) {
    17   ll res = 1;
    18   
    19   for(int i = 1; i < n; ++ i) {
    20     for(int j = i + 1; j < n; ++ j) {
    21       while(a[j][i]) {
    22         ll t = a[i][i] / a[j][i];
    23  
    24         for(int k = i; k < n; ++ k)
    25           a[i][k] = (a[i][k] - a[j][k] * t);
    26         for(int k = i; k < n; ++ k)
    27           swap(a[i][k], a[j][k]);
    28         res = -res;
    29       }
    30     }
    31     if(a[i][i] == 0) return 0;
    32     res = 1LL * res * a[i][i];
    33   }
    34   return res;
    35 }
    36  
    37 void Input() {
    38   int x, y;
    39  
    40   memset(self, 0, sizeof self);
    41   memset(degree, 0, sizeof degree);
    42   
    43   scanf("%d%d", &n, &m);
    44   for(int i = 1; i <= m; ++ i) {
    45     scanf("%d%d", &x, &y);
    46     degree[x][y] ++;
    47     degree[y][x] ++;
    48     self[x][x] ++; self[y][y] ++;
    49   }
    50   for(int i = 1; i <= n; ++ i) {
    51     for(int j = 1; j <= n; ++ j) {
    52       G[i][j] = self[i][j] - degree[i][j];
    53     }
    54   }
    55 }
    56  
    57 void Solve() {
    58   ans = det(G);
    59 }
    60  
    61 void Output() {
    62   printf("%lld
    ", ans);
    63 }
    64  
    65 int main() {
    66   int t;
    67  
    68   scanf("%d", &t);
    69  
    70   while(t --) {
    71     Input();
    72     Solve();
    73     Output();
    74   }
    75  
    76   return 0;
    77 }
    SPOJ 104

    题目4: BZOJ 4031 [HEOI 2015] 小Z的房间

    题目大意:并没有搞懂。只是抄的。河北的题还真是够呛。(PS:我是河北的)

    算法讨论:裸上Matrix-Tree定理吧。

     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 const int N = 15;
     6 const int mod = 1e9;
     7 typedef long long ll;
     8 
     9 int n, m, cnt;
    10 int p[N][N]; ll a[N * N][N * N];
    11 int dx[]={0, 0, 1, -1};
    12 int dy[]={1, -1, 0, 0};
    13 char maze[N][N];
    14 
    15 ll det() {
    16   ll res = 1;
    17 
    18   for(int i = 1; i < cnt; ++ i)
    19     for(int j = 1; j < cnt; ++ j)
    20       a[i][j] = (a[i][j] + mod) % mod;
    21   for(int i = 1; i < cnt; ++ i) {
    22     for(int j = i + 1; j < cnt; ++ j) {
    23       while(a[j][i]) {
    24         ll t = a[i][i] / a[j][i];
    25         
    26         for(int k = i; k < cnt; ++ k)
    27           a[i][k] = (a[i][k] - a[j][k] * t % mod + mod) % mod;
    28         for(int k = i; k < cnt; ++ k)
    29           swap(a[i][k], a[j][k]);
    30         res = -res;
    31       }
    32     }
    33     if(a[i][i] == 0) return 0;
    34     res = 1LL * res * a[i][i] % mod;
    35   }
    36   return (res + mod) % mod;
    37 }
    38 
    39 int main() {
    40   scanf("%d%d", &n, &m);
    41   for(int i = 1; i <= n; ++ i) {
    42     scanf("%s", maze[i] + 1);
    43   }
    44   for(int i = 1; i <= n; ++ i) 
    45     for(int j = 1; j <= m; ++ j)
    46       if(maze[i][j] == '.')
    47         p[i][j] = ++ cnt;
    48   for(int i = 1; i <= n; ++ i) {
    49     for(int j = 1; j <= m; ++ j) {
    50       if(maze[i][j] != '.') continue;
    51       for(int k = 0; k < 4; ++ k) {
    52         int nx = dx[k] + i, ny = dy[k] + j;
    53 
    54         if(nx < 1 || ny < 1 || nx > n || ny > m || maze[nx][ny] != '.') continue;
    55         int u = p[i][j], v = p[nx][ny];
    56 
    57         a[u][u] ++; a[u][v] --;
    58       }
    59     }
    60   }
    61   printf("%lld
    ", det());
    62   return 0;
    63 }
    BZOJ 4031

    题目5: Uva 10766

    题目大意:

    求一个有根树的生成树的数量。

    算法讨论:

    其实这个有根和无根是一样的。直接做就行。

     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 typedef long long ll;
     6 const int N = 55;
     7 
     8 int n, m, kk;
     9 bool lk[N][N];
    10 ll a[N][N];
    11 
    12 ll det() {
    13   ll res = 1;
    14   
    15   for(int i = 1; i < n; ++ i) {
    16     for(int j = i + 1; j < n; ++ j) {
    17       while(a[j][i]) {
    18         ll t = a[i][i] / a[j][i];
    19 
    20         for(int k = i; k < n; ++ k)
    21           a[i][k] = a[i][k] - a[j][k] * t;
    22         for(int k = i; k < n; ++ k)
    23           swap(a[i][k], a[j][k]);
    24         res = -res;
    25       }
    26     }
    27     if(a[i][i] == 0) return 0;
    28     res = res * a[i][i];
    29   }
    30 
    31   return abs(res);
    32 }
    33 
    34 int main() {
    35   int u, v;
    36   
    37   while(~scanf("%d%d%d", &n, &m, &kk)) {
    38     memset(lk, false, sizeof lk);
    39     memset(a, 0, sizeof a);
    40     for(int i = 1; i <= m; ++ i) {
    41       scanf("%d%d", &u, &v);
    42       lk[u][v] = lk[v][u] = true;
    43     }
    44     for(int i = 1; i <= n; ++ i) {
    45       int cnt = 0;
    46 
    47       for(int j = 1; j <= n; ++ j) {
    48         if(i != j && !lk[i][j]) {
    49           a[i][j] = -1;
    50           ++ cnt;
    51         }
    52       }
    53       a[i][i] = cnt;
    54     }
    55     printf("%lld
    ", det());
    56   }
    57 
    58   return 0;
    59 }
    Uva 10766

    题目6: BZOJ1016 && JSOI2008最小生成树计数

    题目大意:

    求一个图的最小生成树的个数。

    算法讨论:

    将边权从小到大SORT。然后对于相同边权的做一次处理进行缩点。如果缩点后出现多个联通块,有两种方法:对每个联通块做Matrix-Tree,然后相乘,或者在两个联通块加一个桥,这样方案数不会受影响。

    坑点就是最后如果有形不成树的情况。

    代码:

      1 #include <cstdlib>
      2 #include <iostream>
      3 #include <cstdio>
      4 #include <cstring>
      5 #include <algorithm>
      6 #include <vector>
      7 
      8 using namespace std;
      9 const int N = 100 + 5;
     10 const int M = 1000 + 5;
     11 const int mod = 31011;
     12 typedef long long ll;
     13 
     14 int n, m, tim, cnt;
     15 ll A[N][N], ans = 1;
     16 int fa[N], lab[N], repos[N], f2[N];
     17 
     18 struct Edge {
     19     int u, v, d;
     20     bool operator < (const Edge &k) const {
     21         return d < k.d;
     22     }
     23 }e[M];
     24 vector <Edge> p[N];
     25 
     26 void Init() {
     27     scanf("%d%d", &n, &m);
     28     for(int i = 1; i <= m; ++ i) {
     29         scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].d);
     30     }
     31 }
     32 
     33 ll Det(ll a[N][N], int ns) {
     34     ll res = 1;
     35     for(int i = 1; i < ns; ++ i) {
     36         for(int j = i + 1; j < ns; ++ j) {
     37             while(a[j][i]) {
     38                 ll t = a[i][i] / a[j][i];
     39                 for(int k = i; k < ns; ++ k)
     40                     a[i][k] = (a[i][k] - a[j][k] * t);
     41                 for(int k = i; k < ns; ++ k)
     42                     swap(a[i][k], a[j][k]);
     43                 res = -res;
     44             }
     45         }
     46         if(a[i][i] == 0) return 0;
     47         res = res * a[i][i];
     48     }    
     49     return res;
     50 }
     51 
     52 int find(int *f, int x) {
     53     return f[x] == x ? x : (f[x] = find(f, f[x]));
     54 }
     55 
     56 void Work(vector <Edge> &v) {
     57     vector <Edge> :: iterator it;
     58     int poi = 0;
     59     ++ tim;
     60     for(it = v.begin(); it != v.end(); ++ it) {
     61         if(lab[fa[(*it).u]] != tim) {
     62             lab[fa[(*it).u]] = tim; 
     63             repos[fa[(*it).u]] = ++ poi;
     64         }
     65         if(lab[fa[(*it).v]] != tim) {
     66             lab[fa[(*it).v]] = tim;
     67             repos[fa[(*it).v]] = ++ poi;
     68         }
     69     }    
     70     for(int i = 1; i <= poi; ++ i) 
     71         for(int j = 1; j <= poi; ++ j)
     72             A[i][j] = 0;
     73     for(it = v.begin(); it != v.end(); ++ it) {
     74         -- A[repos[fa[(*it).u]]][repos[fa[(*it).v]]];
     75         -- A[repos[fa[(*it).v]]][repos[fa[(*it).u]]];
     76         ++ A[repos[fa[(*it).u]]][repos[fa[(*it).u]]];
     77         ++ A[repos[fa[(*it).v]]][repos[fa[(*it).v]]];
     78     }
     79     ans = ans * Det(A, poi) % mod;
     80 }
     81 
     82 void Calc(int l, int r) {
     83     for(int i = l; i <= r; ++ i) {
     84         f2[fa[e[i].u]] = fa[e[i].u];
     85         f2[fa[e[i].v]] = fa[e[i].v];
     86         p[fa[e[i].u]].clear();
     87         p[fa[e[i].v]].clear();
     88     }
     89     for(int i = l; i <= r; ++ i) {
     90         f2[find(f2, fa[e[i].u])] = find(f2, fa[e[i].v]);
     91     }
     92     for(int i = l; i <= r; ++ i) {
     93         if(fa[e[i].u] != fa[e[i].v]) {
     94             p[find(f2, fa[e[i].u])].push_back(e[i]);
     95         }
     96     }
     97     for(int i = l; i <= r; ++ i) {
     98         if(!p[fa[e[i].u]].empty()) {
     99             Work(p[fa[e[i].u]]), p[fa[e[i].u]].clear();
    100         }
    101         if(!p[fa[e[i].v]].empty()) {
    102             Work(p[fa[e[i].v]]), p[fa[e[i].v]].clear();
    103         }
    104     }
    105 }
    106 
    107 void Solve() {
    108     sort(e + 1, e + m + 1);
    109     cnt = n;
    110     for(int i = 1; i <= n; ++ i) fa[i] = i;
    111     for(int i = 1; i <= m && cnt > 1;) {
    112         int j = i;
    113         for(; e[j].d == e[i].d && j <= m; ++ j) {
    114             find(fa, e[j].u); find(fa, e[j].v);
    115         }
    116         Calc(i, j - 1);
    117         for(int k = i; k < j; ++ k) {
    118             int fx = find(fa, e[k].u), fy = find(fa, e[k].v);
    119             if(fx != fy) {
    120                 fa[fx] = fy;
    121                 cnt --;
    122             }
    123         }
    124         i = j;
    125     }
    126     if(cnt != 1) ans = 0;
    127     printf("%lld
    ", ans % mod);
    128 }
    129 
    130 #define stone_eee
    131 int main() {
    132 #ifndef stone_
    133     freopen("mst.in", "r", stdin);
    134     freopen("mst.out", "w", stdout);
    135 #endif
    136 
    137     Init();
    138     Solve();
    139 
    140 #ifndef stone_
    141     fclose(stdin); fclose(stdout);
    142 #endif
    143     return 0;
    144 }
    1016
  • 相关阅读:
    概率期望小记
    洛谷P5591 小猪佩奇学数学【单位根反演】
    EasyUI取消树节点选中
    EasyUI获取正在编辑状态行的索引
    js判断是否是大小写,数字等方法
    ElasticSearch部署问题
    全文检索ES 服务启动和关闭
    文件异步上传
    js控制时间显示格式
    SpringMVC 多视图解析器 跳转问题
  • 原文地址:https://www.cnblogs.com/sxprovence/p/5188747.html
Copyright © 2020-2023  润新知