A Knight
留坑。
B Tree
思路:两次树形DP,但是要考虑0没有逆元
可以用前缀后缀做
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 1000010 5 #define ll long long 6 7 const ll MOD = (ll)1e9 + 7; 8 9 10 int n; 11 ll dp[N], dp2[N]; 12 ll prefix[N], suffix[N]; 13 vector <int> G[N]; 14 15 void Init() 16 { 17 for (int i = 1; i <= n; ++i) dp[i] = 1, dp2[i] = 0, G[i].clear(); 18 } 19 20 void DFS(int u, int fa) 21 { 22 for (auto v : G[u]) 23 { 24 if (v == fa) continue; 25 DFS(v, u); 26 dp[u] = dp[u] * (dp[v] + 1) % MOD; 27 } 28 } 29 30 void DFS2(int u, int fa) 31 { 32 prefix[0] = 1; 33 suffix[G[u].size() + 1] = 1; 34 int len = G[u].size(); 35 for (int i = 0; i < len; ++i) 36 { 37 int v = G[u][i]; 38 if (v == fa) prefix[i + 1] = prefix[i]; 39 else prefix[i + 1] = prefix[i] * (dp[G[u][i]] + 1) % MOD; 40 } 41 for (int i = len - 1; i >= 0; --i) 42 { 43 int v = G[u][i]; 44 if (v == fa) suffix[i + 1] = suffix[i + 2]; 45 else suffix[i + 1] = suffix[i + 2] * (dp[G[u][i]] + 1) % MOD; 46 47 } 48 for (int i = 0; i < len; ++i) 49 { 50 int v = G[u][i]; 51 if (v == fa) continue; 52 dp2[v] = prefix[i] % MOD * suffix[i + 2] % MOD * (dp2[u] + 1) % MOD; 53 } 54 for (auto v : G[u]) 55 { 56 if (v == fa) continue; 57 DFS2(v, u); 58 } 59 } 60 61 void Run() 62 { 63 while (scanf("%d", &n) != EOF) 64 { 65 Init(); 66 for (int i = 1, u, v; i < n; ++i) 67 { 68 scanf("%d%d", &u, &v); 69 G[u].push_back(v); 70 G[v].push_back(u); 71 } 72 DFS(1, 0); DFS2(1, 0); 73 for (int i = 1; i <= n; ++i) printf("%lld\n", dp[i] * (dp2[i] + 1) % MOD); 74 } 75 } 76 77 int main() 78 { 79 #ifdef LOCAL 80 freopen("Test.in", "r", stdin); 81 #endif 82 83 Run(); 84 return 0; 85 }
C Two Graphs
留坑。
D Shopping
贪心即可。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 1010 5 6 int t, n, m; 7 int arr[N], res; 8 9 int main() 10 { 11 scanf("%d", &t); 12 while (t--) 13 { 14 res = 0; 15 scanf("%d%d", &n, &m); 16 for (int i = 1, b; i <= n; ++i) 17 { 18 scanf("%d%d", arr + i, &b); 19 if (b) ++res; 20 } 21 sort(arr + 1, arr + 1 + n); 22 res = min(res, m); 23 double ans = 0; 24 for (int i = n; i >= 1; --i, --res) 25 ans += res > 0 ? arr[i] * 1.0 / 2 : arr[i]; 26 printf("%.1f\n", ans); 27 } 28 return 0; 29 }
E Trophies
留坑。
F Palindrome
留坑。
G Stones
留坑。
H Travel
思路:隔板法,一条边相当于划成两个区域。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define ll long long 5 #define N 100010 6 7 const ll MOD = (ll)1e9 + 7; 8 9 ll fac[N]; 10 11 void Init() 12 { 13 fac[0] = 1; 14 for (int i = 1; i < N; ++i) fac[i] = fac[i - 1] * i % MOD; 15 } 16 17 ll qpow(ll base, ll n) 18 { 19 ll res = 1; 20 while (n) 21 { 22 if (n & 1) res = res * base % MOD; 23 base = base * base % MOD; 24 n >>= 1; 25 } 26 return res; 27 } 28 29 ll C(ll n, ll m) 30 { 31 if (m > n) return 0; 32 return fac[n] * qpow(fac[m] * fac[n - m] % MOD, MOD - 2) % MOD; 33 } 34 35 int t, n, m; 36 37 int main() 38 { 39 Init(); 40 scanf("%d", &t); 41 while (t--) 42 { 43 scanf("%d%d", &n, &m); 44 for (int i = 1, a, b; i < n; ++i) scanf("%d%d", &a, &b); 45 printf("%lld\n", C(n - 1, m - 1) * fac[m] % MOD); 46 } 47 return 0; 48 }
I Metropolis
思路:将所有大都会都放到最短路去跑多源最短路,记录每个点的最短路是由哪个点扩展而来
显然,如果一个点源点i扩展到一个点j, 而点j又已经被点k扩展了,那么就没有必要扩展下去
我们在枚举每一条边,更新答案
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 200010 5 #define ll long long 6 #define INFLL 0x3f3f3f3f3f3f3f3f 7 8 struct Edge 9 { 10 int to, nx; ll w; 11 Edge() {} 12 Edge(int to, int nx, ll w) : to(to), nx(nx), w(w) {} 13 }edge[N << 1]; 14 15 int n, m, p; 16 int head[N], pos; 17 int x[N], Belong[N]; 18 ll dis[N], ans[N]; 19 20 void addedge(int u, int v, ll w) 21 { 22 edge[++pos] = Edge(v, head[u], w); head[u] = pos; 23 } 24 25 struct node 26 { 27 ll w; int u, v; 28 node() {} 29 node(int u, int v, ll w) : u(u), v(v), w(w) {} 30 bool operator < (const node &r) const 31 { 32 return w > r.w; 33 } 34 }; 35 36 priority_queue <node> q; 37 38 void Init() 39 { 40 memset(head, -1, sizeof head); 41 pos = 0; 42 while (!q.empty()) q.pop(); 43 memset(Belong, 0, sizeof Belong); 44 memset(ans, 0x3f, sizeof ans); 45 } 46 47 void Dijkstra() 48 { 49 while (!q.empty()) 50 { 51 node top = q.top(); q.pop(); 52 if (Belong[top.v]) continue; 53 Belong[top.v] = top.u; 54 dis[top.v] = top.w; 55 for (int it = head[top.v]; ~it; it = edge[it].nx) 56 { 57 int v = edge[it].to; 58 q.emplace(top.u, v, top.w + edge[it].w); 59 } 60 } 61 } 62 63 void Run() 64 { 65 while (scanf("%d%d%d", &n, &m, &p) != EOF) 66 { 67 Init(); 68 for (int i = 1; i <= p; ++i) 69 { 70 scanf("%d", x + i); 71 q.emplace(x[i], x[i], 0); 72 } 73 for (int i = 1, u, v, w; i <= m; ++i) 74 { 75 scanf("%d%d%d", &u, &v, &w); 76 addedge(u, v, w); 77 addedge(v, u, w); 78 } 79 Dijkstra(); 80 for (int u = 1; u <= n; ++u) 81 { 82 for (int it = head[u]; ~it; it = edge[it].nx) 83 { 84 int v = edge[it].to; 85 ll w = edge[it].w; 86 if (Belong[u] == Belong[v]) continue; 87 ans[Belong[u]] = min(ans[Belong[u]], dis[u] + dis[v] + w); 88 ans[Belong[v]] = min(ans[Belong[v]], dis[u] + dis[v] + w); 89 } 90 } 91 for (int i = 1; i <= p; ++i) printf("%lld%c", ans[x[i]], " \n"[i == p]); 92 } 93 } 94 95 int main() 96 { 97 #ifdef LOCAL 98 freopen("Test.in", "r", stdin); 99 #endif 100 101 Run(); 102 return 0; 103 }
J Graph Coloring I
思路:对于一张图,如果没有奇圈,那么肯定可以用两种颜色进行染色,那么肯定有解
只要去找奇圈即可。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 300010 5 6 int n, m; 7 vector <int> G[N], ans; 8 int deep[N], fa[N]; 9 bool flag; 10 11 void DFS(int u) 12 { 13 if (flag) return; 14 for (auto v : G[u]) 15 { 16 if (flag) return; 17 if (v == fa[u]) continue; 18 if (fa[v] != -1 && !flag) 19 { 20 if ((deep[u] - deep[v]) % 2 == 0) 21 { 22 ans.push_back(u); 23 while (u != v) 24 { 25 u = fa[u]; 26 ans.push_back(u); 27 } 28 flag = true; 29 return; 30 } 31 } 32 else 33 { 34 fa[v] = u; 35 deep[v] = deep[u] + 1; 36 DFS(v); 37 } 38 } 39 } 40 41 void Init() 42 { 43 for (int i = 1; i <= n; ++i) G[i].clear(); 44 ans.clear(); 45 memset(fa, -1, sizeof fa); 46 deep[1] = 0; 47 flag = false; 48 } 49 50 int main() 51 { 52 while (scanf("%d%d", &n, &m) != EOF) 53 { 54 Init(); 55 for (int i = 1, u, v; i <= m; ++i) 56 { 57 scanf("%d%d", &u, &v); 58 G[u].push_back(v); 59 G[v].push_back(u); 60 } 61 DFS(1); 62 if (flag) 63 { 64 printf("%d\n", (int)ans.size()); 65 for (int i = 0, len = ans.size(); i < len; ++i) printf("%d%c", ans[i], " \n"[i == len - 1]); 66 } 67 else 68 { 69 puts("0"); 70 for (int i = 1; i <= n; ++i) printf("%d%c", deep[i] & 1, " \n"[i == n]); 71 } 72 } 73 return 0; 74 }
K Graph Coloring II
留坑。