[BZOJ1543] 生成树计数 (Kruskal)
Description
给定一个连通的带边权的图(允许自环和重边),求不同的最小生成树个数。两个生成树不同当它们所用的边的序号不同,换句话说,重边算多次。
Input
第一行n,m,表示点数和边数(1<=n<=50000,1<=m<=100000) 下接m行,每行3个数k1,k2,w,表示k1和k2之间有一条权值为w 的边。
Output
仅一行一个数:生成树个数 mod 1000003(质数)
Sample Input
3 5
1 2 6
1 2 6
2 3 6
3 1 6
3 3 8
1 2 6
1 2 6
2 3 6
3 1 6
3 3 8
Sample Output
5
注:不会存在5条及5条以上的边,他们的边权是相同的。
样例解释:
5棵生成树分别如下(边按输入顺序标号):
(1,3) (2,3) (1,4) (2,4) (3,4)
5号边是自环。
HINT
Source
Solution
同$BZOJ1016$,感觉如果第一页那题能过,这题也能过。题解依然是我写的。
1 #include <bits/stdc++.h> 2 using namespace std; 3 struct edge 4 { 5 int u, v, w, x; 6 inline bool operator< (const edge &rhs) const 7 { 8 return x < rhs.x; 9 } 10 }e[100005]; 11 struct count 12 { 13 int l, r, use; 14 }g[100005]; 15 int n, m, fa[50005], siz[50005]; 16 17 int getfa(int x) 18 { 19 return fa[x] == x ? x : getfa(fa[x]); 20 } 21 22 void link(int u, int v) 23 { 24 if(siz[u] > siz[v]) fa[v] = u, siz[u] += siz[v]; 25 else fa[u] = v, siz[v] += siz[u]; 26 } 27 28 bool Kruskal() 29 { 30 int cnt = 0, u, v; 31 for(int i = 1; i <= m; ++i) 32 { 33 u = getfa(e[i].u), v = getfa(e[i].v); 34 if(u != v) 35 { 36 link(u, v); 37 ++g[e[i].w].use; 38 if(++cnt == n - 1) return true; 39 } 40 } 41 return false; 42 } 43 44 int DFS(int w, int i, int k) 45 { 46 if(k == g[w].use) return 1; 47 if(i > g[w].r) return 0; 48 int ans = 0, u = getfa(e[i].u), v = getfa(e[i].v); 49 if(u != v) 50 { 51 link(u, v); 52 ans = DFS(w, i + 1, k + 1); 53 fa[u] = u, fa[v] = v; 54 } 55 return ans + DFS(w, i + 1, k); 56 } 57 58 int main() 59 { 60 int u, v, w, ans; 61 cin >> n >> m; 62 for(int i = 1; i <= n; ++i) 63 fa[i] = i, siz[i] = 1; 64 for(int i = 1; i <= m; ++i) 65 { 66 cin >> u >> v >> w; 67 e[i] = (edge){u, v, 0, w}; 68 } 69 sort(e + 1, e + m + 1); 70 w = 0; 71 for(int i = 1; i <= m; ++i) 72 if(e[i].x == e[i - 1].x) e[i].w = w; 73 else 74 { 75 g[w].r = i - 1; 76 e[i].w = ++w; 77 g[w].l = i; 78 } 79 g[w].r = m; 80 ans = Kruskal(); 81 for(int i = 1; i <= n; ++i) 82 fa[i] = i, siz[i] = 1; 83 for(int i = 1; i <= w; ++i) 84 { 85 ans = ans * DFS(i, g[i].l, 0) % 1000003; 86 for(int j = g[i].l; j <= g[i].r; ++j) 87 { 88 u = getfa(e[j].u), v = getfa(e[j].v); 89 if(u != v) link(u, v); 90 } 91 } 92 cout << ans << endl; 93 return 0; 94 }