2018-2019 ACM-ICPC, Asia Xuzhou Regional Contest Solution

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\n", 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 }
View Code

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\n", res);
109     }
110     return 0;
111 }
View Code

猜你喜欢

转载自www.cnblogs.com/Dup4/p/10133077.html