A. Rikka with Minimum Spanning Trees
题意:
给出一个图,求最小生成树的个数和权值
思路:
因为数据随机,只有一个MST
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define ull unsigned long long 5 ull k1, k2; 6 const ull MOD = (ull)1e9 + 7; 7 int t, n, m; 8 9 ull f() 10 { 11 ull k3 = k1, k4 = k2; 12 k1 = k4; 13 k3 ^= k3 << 23; 14 k2 = k3 ^ k4 ^ (k3 >> 17) ^ (k4 >> 26); 15 return k2 + k4; 16 } 17 18 struct Edge 19 { 20 int u, v; ull w; 21 Edge() {} 22 Edge(int u, int v, ull w) : u(u), v(v), w(w) {} 23 bool operator < (const Edge &other) const { return w < other.w; } 24 }edge[100010]; 25 26 int fa[100010]; 27 int find(int x) { return fa[x] == 0 ? x : fa[x] = find(fa[x]); } 28 29 void Kruskal() 30 { 31 memset(fa, 0, sizeof fa); 32 sort(edge + 1, edge + 1 + m); 33 int cnt = 1; 34 ull res = 0; 35 for (int i = 1; i <= m; ++i) 36 { 37 int u = edge[i].u, v = edge[i].v; ull w = edge[i].w; 38 // cout << i << " " << w << endl; 39 int fu = find(u), fv = find(v); 40 if (fu == fv) continue; 41 ++cnt; 42 res = (res + w) % MOD; 43 fa[fu] = fv; 44 if (cnt == n) break; 45 } 46 if (cnt != n) res = 0; 47 printf("%llu ", res); 48 } 49 50 int main() 51 { 52 scanf("%d", &t); 53 while (t--) 54 { 55 scanf("%d%d%llu%llu", &n, &m, &k1, &k2); 56 for (int i = 1; i <= m; ++i) 57 { 58 edge[i].u = f() % n + 1; 59 edge[i].v = f() % n + 1; 60 edge[i].w = f(); 61 // cout << edge[i].u << " " << edge[i].v << " " << edge[i].w << endl; 62 } 63 Kruskal(); 64 } 65 return 0; 66 }
G. Rikka with Intersections of Paths
题意:
给出一棵树,以及$m条简单路径,求从这些简单路径中选出k条,有多少种不同方式使得路径交至少为1$
思路:
枚举路径交的$LCA$, 对于一个点来说,它的贡献是,所有经过它的路径假设为$x$
那么有$C_x^k$ 但是对于一些路径的$LCA不是它,那么这些路径中选出k条的贡献肯定在他们所在的LCA处被计算$
所以应该被减去,也就是说假设经过它但是$LCA不是它的路径条数假设为y条$
那么需要减去$C_y^k$
最终贡献为$C_x^k - C_y^k$
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define ll long long 5 #define N 300010 6 const ll MOD = (ll)1e9 + 7; 7 int t, n, m, k; 8 vector <int> G[N]; 9 10 int fa[N], deep[N], sze[N], son[N], top[N]; 11 void DFS(int u) 12 { 13 sze[u] = 1; 14 for (auto v : G[u]) if (v != fa[u]) 15 { 16 fa[v] = u; 17 deep[v] = deep[u] + 1; 18 DFS(v); 19 sze[u] += sze[v]; 20 if (!son[u] || sze[v] > sze[son[u]]) son[u] = v; 21 } 22 } 23 24 void getpos(int u, int sp) 25 { 26 top[u] = sp; 27 if (!son[u]) return; 28 getpos(son[u], sp); 29 for (auto v : G[u]) if (v != fa[u] && v != son[u]) 30 getpos(v, v); 31 } 32 33 int querylca(int u, int v) 34 { 35 while (top[u] != top[v]) 36 { 37 if (deep[top[u]] < deep[top[v]]) swap(u, v); 38 u = fa[top[u]]; 39 } 40 return deep[u] > deep[v] ? v : u; 41 } 42 43 int cnt[N], tag[N]; 44 void add(int u) 45 { 46 for (auto v : G[u]) if (v != fa[u]) 47 { 48 add(v); 49 cnt[u] += cnt[v]; 50 } 51 } 52 53 ll fac[N], inv[N]; 54 ll qmod(ll base, ll n) 55 { 56 ll res = 1; 57 while (n) 58 { 59 if (n & 1) res = (res * base) % MOD; 60 base = (base * base) % MOD; 61 n >>= 1; 62 } 63 return res; 64 } 65 66 void init() 67 { 68 fac[0] = 1; 69 for (int i = 1; i <= 300000; ++i) fac[i] = (fac[i - 1] * i) % MOD; 70 inv[300000] = qmod(fac[300000], MOD - 2); 71 for (int i = 300000; i >= 1; --i) inv[i - 1] = (inv[i] * i) % MOD; 72 } 73 74 ll C(int n, int m) 75 { 76 if (m > n) return 0; 77 return fac[n] * inv[m] % MOD * inv[n - m] % MOD; 78 } 79 80 int main() 81 { 82 init(); 83 scanf("%d", &t); 84 while (t--) 85 { 86 scanf("%d%d%d", &n, &m, &k); 87 for (int i = 1; i <= n; ++i) G[i].clear(), son[i] = 0, cnt[i] = 0, tag[i] = 0; 88 for (int i = 1, u, v; i <= n - 1; ++i) 89 { 90 scanf("%d%d", &u, &v); 91 G[u].push_back(v); 92 G[v].push_back(u); 93 } 94 DFS(1); getpos(1, 1); 95 for (int i = 1, u, v; i <= m; ++i) 96 { 97 scanf("%d%d", &u, &v); 98 int lca = querylca(u, v); 99 ++tag[lca]; 100 ++cnt[u]; 101 ++cnt[v]; 102 --cnt[lca]; 103 if (fa[lca]) --cnt[fa[lca]]; 104 } 105 add(1); 106 ll res = 0; 107 for (int i = 1; i <= n; ++i) res = (res + C(cnt[i], k) - C(cnt[i] - tag[i], k) + MOD) % MOD; 108 printf("%lld ", res); 109 } 110 return 0; 111 }