HDU 4408 Minimum Spanning Tree 最小生成树计数裸题

来源:互联网 发布:淘宝披肩外套 编辑:程序博客网 时间:2024/04/30 23:54

题意:

给定n个点m条无向边 答案取模 MOD

问:

有多少个最小生成树

DET模版:

#pragma comment(linker, "/STACK:1024000000,1024000000")#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>template <class T>inline bool rd(T &ret) {char c; int sgn;if (c = getchar(), c == EOF) return 0;while (c != '-' && (c<'0' || c>'9')) c = getchar();sgn = (c == '-') ? -1 : 1;ret = (c == '-') ? 0 : (c - '0');while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');ret *= sgn;return 1;}template <class T>inline void pt(T x) {if (x <0) {putchar('-');x = -x;}if (x>9) pt(x / 10);putchar(x % 10 + '0');}using namespace std;typedef long long ll;const int N = 105;    //点的个数const int M = 1005;  //边的个数//点标从1-nstruct node {int set[N];void init(int n) {for (int i = 0; i <= n; i++) set[i] = i;}int find(int x) {return x == set[x] ? x : set[x] = find(set[x]);}int Union(int x, int y) {int xx = find(x);int yy = find(y);if (xx == yy) return -1;set[xx] = yy;return 1;}}a, b, c;struct Node {int u, v, dis;}edge[M];int edgenum;void add(int u, int v, int d){Node E = { u, v, d };edge[++edgenum] = E;}bool visit[N];vector<int> g[N];ll p[N][N], deg[N][N];int cmp(Node a, Node b) {return a.dis < b.dis;}ll DET(ll a[][N], int n, ll MOD){int i, j, k;ll temp = 1, t;for (i = 0; i < n; i++) for (j = 0; j < n; j++) a[i][j] %= MOD;for (i = 1; i < n; i++){for (j = i + 1; j < n; j++) while (a[j][i]){t = a[i][i] / a[j][i];for (k = i; k < n; k++){a[i][k] -= a[j][k] * t;a[i][k] %= MOD;}for (k = i; k < n; k++)swap(a[i][k], a[j][k]);temp = -temp;}temp = temp*a[i][i] % MOD;}return (temp + MOD) % MOD;}ll cal_MST_count(int n, ll MOD) {sort(edge + 1, edge + edgenum + 1, cmp);int pre = edge[1].dis;ll ans = 1;a.init(n);b.init(n);memset(visit, 0, sizeof(visit));memset(deg, 0, sizeof(deg));for (int i = 0; i <= n; i++) g[i].clear();for (int t = 1; t <= edgenum + 1; t++){if (edge[t].dis != pre || t == edgenum + 1){for (int i = 1, k; i <= n; i++) if (visit[i]){k = b.find(i);g[k].push_back(i);visit[i] = 0;}for (int i = 1; i <= n; i++)if (g[i].size()){memset(p, 0, sizeof(p));for (int j = 0; j < g[i].size(); j++)for (int k = j + 1, x, y; k < g[i].size(); k++){x = g[i][j];y = g[i][k];p[j][k] = p[k][j] = -deg[x][y];p[j][j] += deg[x][y];p[k][k] += deg[x][y];}ans = ans*DET(p, g[i].size(), MOD) % MOD;for (int j = 0; j < g[i].size(); j++) a.set[g[i][j]] = i;}memset(deg, 0, sizeof(deg));for (int i = 1; i <= n; i++){b.set[i] = a.find(i);g[i].clear();}if (t == edgenum + 1) break;pre = edge[t].dis;}int x = a.find(edge[t].u);int y = a.find(edge[t].v);if (x == y) continue;visit[x] = visit[y] = 1;b.Union(x, y);deg[x][y]++;deg[y][x]++;}if (!edgenum) return 0;for (int i = 2; i <= n; i++)if (b.find(i) != b.find(1))return 0;return ans;}void init(){ edgenum = 0; }int n, m, u, v, d;ll mod;int main(){while (cin >> n >> m >> mod, n + m + mod){init();while (m--){rd(u); rd(v); rd(d);add(u, v, d);}pt(cal_MST_count(n, mod)); putchar('\n');}return 0;}


0 0
原创粉丝点击