模板-最小生成树计数
来源:互联网 发布:淘宝上取消了分流 编辑:程序博客网 时间:2024/06/05 11:25
//最小生成树计数#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
- 模板-最小生成树计数
- 最小生成生成树计数
- 最小生成树计数模版
- [JSOI2008]最小生成树计数
- 【最小生成树计数】【下标】
- bzoj1016【最小生成树计数】
- bzoj1006 最小生成树计数
- bzoj1016 最小生成树计数
- 最小生成树模板
- 最小生成树模板
- 最小生成树---模板
- 最小生成树模板
- 最小生成树 模板
- 最小生成树(模板)
- 最小生成树模板
- 最小生成树模板
- 最小生成树模板
- 最小生成树【模板】
- 抽象工厂
- Redis, Memcache, Mysql区别
- HDU 1423 Greatest Common Increasing Subsequence
- HDU 1873 看病要排队 优先队列
- UI_UITableView _新知识_02
- 模板-最小生成树计数
- bzoj1375[Baltic2002]Bicriterial routing 双调路径
- POJ 3237 Tree 树链剖分 边权
- C++Primer第五版 7.5.2节练习
- Pro/E环境下的弧齿锥齿轮三维参数化造型
- 视频编解码学习之一:理论基础
- PHP中静态(static)调用非静态方法详解
- C++Primer第五版 7.5.3节练习
- ARM7学习笔记——中断向量控制器VIC