1. 程式人生 > >2018-2019 ACM-ICPC, Asia Xuzhou Regional Contest Solution

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