hdu 4408 最小生成树计数
2013-04-30 19:43
190 查看
经典题了
#include <utility> #include <algorithm> #include <string> #include <cstring> #include <cstdio> #include <iostream> #include <iomanip> #include <set> #include <vector> #include <cmath> #include <queue> #include <bitset> #include <map> #include <iterator> using namespace std; #define clr(a,v) memset(a,v,sizeof(a)) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 const int INF = 0x7f7f7f7f; const int maxn = 211; const double pi = acos(-1.0); const double eps = 1e-10; typedef long long ll; typedef pair<int, int> pii; typedef vector<int> VI; typedef vector<VI> VVI; typedef vector<VVI> VVVI; typedef pair<int, int> pii; int deg[maxn][maxn]; ll det[maxn][maxn]; int G[maxn][maxn]; int n, m, p, mod; vector<pii>::iterator it; int f[maxn], g[maxn]; int find(int n, int f[]) { return f == n ? n : f = find(f , f); } bool vis[maxn]; ll Det(int n) { int i, j, k; ll ans = 1, t; for (i = 0; i < n; ++i) { for (j = i + 1; j < n; ++j) { while (det[j][i]) { t = det[i][i] / det[j][i]; for (k = i; k < n; ++k) { det[i][k] -= det[j][k] * t; det[i][k] %= mod; swap(det[i][k], det[j][k]); } ans *= -1; } } if (!det[i][i]) return 0; } for (i = 0; i < n; ++i) { ans = ans * det[i][i] % mod; } ans = (ans % mod + mod) % mod; return ans; } int main() { int i, j, u, v, w; int p, q; while (~scanf("%d%d%d", &n, &m, &p) && (n | m | p)) { mod = p; memset(G, 0, sizeof(G)); for (i = 0; i < n; ++i) f[i] = g[i] = i; vector<pii> V[12]; vector<int> gra[maxn]; for (i = 0; i < m; ++i) { scanf("%d%d%d", &u, &v, &w); --u, --v; V[w].push_back(pii(u, v)); } if (!m) { puts("0"); continue; } int sz; ll ans = 1; memset(vis, false, sizeof(vis)); for (i = 1; i <= 10; ++i) { if (V[i].empty()) continue; sz = V[i].size(); for (it = V[i].begin(); it != V[i].end(); ++it) { u = it->first; v = it->second; u = find(u, f); v = find(v, f); if (u == v) continue; vis[u] = vis[v] = true; G[u][v]++; G[v][u]++; u = find(u, g); v = find(v, g); g[u] = v; } for (j = 0; j < n; ++j) { if (!vis[j]) continue; vis[j] = false; u = find(j, g); gra[u].push_back(j); } for (j = 0; j < n; ++j) { if ((int) gra[j].size() > 1) { sz = gra[j].size(); for (p = 0; p < sz; ++p) for (q = 0; q < sz; ++q) det[p][q] = 0; for (p = 0; p < sz; ++p) { for (q = p + 1; q < sz; ++q) { u = gra[j][p]; v = gra[j][q]; det[p][q] = det[q][p] = -G[u][v]; det[p][p] += G[u][v]; det[q][q] += G[v][u]; } } ll t = Det(sz - 1); ans = ans * t % mod; } } for (j = 0; j < n; ++j) f[j] = g[j] = find(j, g), gra[j].clear(); } bool flag = true; for (i = 1; i < n && flag; ++i) { if (f[i] != f[i - 1]) { flag = false; break; } } if (!flag) ans = 0; printf("%I64d\n", ans); } return 0; }
相关文章推荐
- HDU 4408 - Minimum Spanning Tree(最小生成树计数)
- HDU 4408 Minimum Spanning Tree(最小生成树计数)
- HDU 4408 Minimum Spanning Tree 最小生成树计数裸题
- HDU 4408 Minimum Spanning Tree 最小生成树计数
- hdu 4408 Minimum Spanning Tree 最小生成树计数
- 【HDU 4408】Minimum Spanning Tree(最小生成树计数)
- [矩阵树定理 模板题] BZOJ 1016 [JSOI2008]最小生成树计数 & HDU 4408 Minimum Spanning Tree
- HDU 4408 Minimum Spanning Tree (图的最小生成树计数 Kruskal + Matrix_Tree定理)
- 最小生成树计数 bzoj 1016 hdu 4408
- HDU 4408 Minimum Spanning Tree(最小生成树计数)
- HDU 4408 Minimum Spanning Tree(最小生成树计数)
- HDU 4408 最小生成树的个数
- hdu 1875畅通工程再续(最小生成树)
- hdu 还是畅通工程 (基础)(最小生成树)(Prim算法 && Kruskal算法)
- HDU_1879 畅通工程(最小生成树)
- hdu 畅通工程再续(最小生成树)(Prim算法 && Kruskal算法)
- 【最小生成树】(模板-kruskal算法)hdu 1863 畅通工程
- HDU 2489 DFS枚举+最小生成树
- HDU 4463 最小生成树 裸题
- hdu 4253(二分+最小生成树)