hdu 4408 Minimum Spanning Tree
2012-11-12 16:41
465 查看
题目连接:点击打开链接
解法:利用kruskal算法 把图划分成森林, 同一点有相同最小的权值到别的点, 通过determinant计算树的课数。
总结:模板 + 自己不太懂 = 记录 + 重新学
代码君:
解法:利用kruskal算法 把图划分成森林, 同一点有相同最小的权值到别的点, 通过determinant计算树的课数。
总结:模板 + 自己不太懂 = 记录 + 重新学
代码君:
#include <stdio.h> #include <iostream> #include <vector> #define LL long long using namespace std; const int MAX = 105; const int MAXE = 1005; struct node { int set[MAX]; void init(int n) { for (int i = 0; i <= n; i++) set[i] = i; } int find(int x) { if (set[x] != x) set[x] = find(set[x]); return 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; } }; struct Node { int u, v, dis; }; node a, b, c; int n, m; Node e[MAXE]; int visit[MAX]; vector<int> g[MAX]; LL p[MAX][MAX], MOD, deg[MAX][MAX]; bool cmp(Node a, Node b) { return a.dis < b.dis; } LL DET(LL a[][MAX], int n) { LL temp = 1, t; for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) a[i][j] %= MOD; for (int i = 1; i < n; i++) { for (int j = i + 1; j < n; j++) while (a[j][i]) { t = a[i][i] / a[j][i]; for (int k = i; k < n; k++) { a[i][k] -= a[j][k] * t; a[i][k] %= MOD; } for (int k = i; k < n; k++) { t = a[i][k]; a[i][k] = a[j][k]; a[j][k] = t; } temp = -temp; } temp = temp * a[i][i] % MOD; } return (temp + MOD) % MOD; } LL cal_MST_cout() { sort(e + 1, e + m + 1, cmp); int pre = e[1].dis; LL ans = 1; a.init(n); b.init(n); memset(visit, false, sizeof(visit)); memset(deg, false, sizeof(deg)); for (int i = 0; i <= n; i++) g[i].clear(); for (int t = 1; t <= m + 1; t++) { if (e[t].dis != pre || t == m + 1) { for (int i = 1; i <= n; i++) if (visit[i]) { int 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, false, sizeof(p)); for (int j = 0; j < g[i].size(); j++) for (int k = j + 1; k < g[i].size(); k++) { int x = g[i][j]; int 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; for (int j = 0; j < g[i].size(); j++) a.set[g[i][j]] = i; } memset(deg, false, sizeof(deg)); for (int i = 1; i <= n; i++) { b.set[i] = a.find(i); g[i].clear(); } if (t == m + 1) break; pre = e[t].dis; } int x = a.find(e[t].u); int y = a.find(e[t].v); if (x == y) continue; visit[x] = visit[y] = 1; b.Union(x, y); deg[x][y]++; deg[y][x]++; } if (!m) return false; for (int i = 2; i <= n; i++) if (b.find(i) != b.find(1)) return false; return ans; } int main() { while (~scanf("%d%d%lld", &n, &m, &MOD) && (n | m | MOD)) { for (int i = 1; i <= m; i++) scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].dis); printf("%lld\n", cal_MST_cout()); } }
相关文章推荐
- 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定理)
- 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 最小生成树计数
- HDOJ 题目4408 Minimum Spanning Tree(Kruskal+Matrix_Tree)
- hdu 1223 minimum spanning tree
- hdoj 4408 Minimum Spanning Tree 求最小生成树的数目
- 最小生成树(Minimum Spanning Tree)(Kruskal算法)
- Codeforces Edu3 E. Minimum spanning tree for each edge
- 数据结构与算法分析–Minimum Spanning Tree(最小生成树)
- HDU 4582 DFS spanning tree 解题报告(贪心 & 树形DP)
- HDU 4896 Minimal Spanning Tree(矩阵高速功率)