[关闭]
@dxbdly 2022-10-09T14:51:46.000000Z 字数 4570 阅读 243

10.8模拟赛 —— Violet4

2022秋


Contest_Summary

Expcet:

T1 T2 T3 Sum
20 0 100 120

Present:

T1 T2 T3 Sum Rank
20 0 90 110 3

T1 Rabbit

Description

Solution

首先考虑猜答案,显然是

考虑怎么构造方案,把 个点排成一个圈,可以发现选取公差为 的等差序列,即可使每个点对都正好被覆盖 次。

Code

  1. //The Code Is From Dawn
  2. #include<bits/stdc++.h>
  3. using namespace std;
  4. inline int read() {
  5. int x = 0;
  6. char c = getchar();
  7. bool f = 0;
  8. while(!isdigit(c)) f |= (c == '-'), c = getchar();
  9. while(isdigit(c)) x = (x * 10) + (c ^ 48), c = getchar();
  10. return f ? -x : x;
  11. }
  12. const int maxn = 1005;
  13. int n;
  14. int main() {
  15. // freopen("rabbit.in", "r", stdin);
  16. // freopen("rabbit.out", "w", stdout);
  17. n = read();
  18. printf("%d\n", n * (n - 1) >> 1);
  19. for(register int i = 1; i <= n; ++i)
  20. for(register int j = 1; j <= (n - 1) / 2; ++j)
  21. printf("%d %d %d\n", i, ((i + j) % n == 0 ? n : (i + j) % n), ((i + (j << 1)) % n == 0 ? n : (i + (j << 1)) % n));
  22. return 0;
  23. }

Summary

考场上猜规律猜得太久了,浪费了很多时间。

T2 Travel

Description

Solution

就是 [CTSC2008]祭祀 的前两问。

一道非常好的网络流题,此题就是要求最长反链/最大独立集。

首先有个结论:

最长反链 = 最小可重链覆盖

由于 很小,我们直接传递闭包,把每个点对的连通性求出来,所以对于 DAG:

最长反链 = 最小不可重链覆盖

其实也就是

最大独立集 = n - 最小点覆盖

两种方式理解都可以。

然后套路的把点拆成入点和出点,建出二分图,最大匹配。

最小不可重链覆盖 = n - 最小点覆盖 = n - 最大匹配

第一问的答案就求出来了。

第二问有两种求法:

Sol1

考虑哪些点可能成为最长反链上的点,可以发现如果删去一个点,答案 ,则此点可以是最长反链上的点,称这些点为可行点。

然后做一个染色,任选一个可行点染上颜色 ,并把所有可到达的可行点也染成 ,总颜色数就是答案。

复杂度瓶颈在找可行点,复杂度

Sol2

一个很奇妙的结论:

原图的最大独立集由入点与出点都在二分图最大独立集中的点组成。

考虑感性证明一下这个结论。

如果某点在原图的最大独立集中,拆点后入点与出点一定也在二分图的最大独立集中。

所以把二分图最大独立集中那些单独多出来的点剃掉,应该就是原图的最大独立集(其实证的不完备,理解即可)。

然后就是如何求二分图的最大独立集。

从左侧未匹配点开始,从左往右只跑未匹配边,从右往左只跑匹配边,跑个
那么左侧未被跑到的点与右侧被跑到的点就是最小点覆盖,补集就是最大独立集。

这一部分的复杂度是 ,总复杂度 ,瓶颈在匈牙利与传递闭包。

  1. //The Code Is From Dawn
  2. #include<bits/stdc++.h>
  3. using namespace std;
  4. inline int read() {
  5. int x = 0;
  6. char c = getchar();
  7. bool f = 0;
  8. while(!isdigit(c)) f |= (c == '-'), c = getchar();
  9. while(isdigit(c)) x = (x * 10) + (c ^ 48), c = getchar();
  10. return f ? -x : x;
  11. }
  12. const int maxn = 205, maxm = 4 * 1e4 + 5;
  13. int n, m, Cnt;
  14. int mapp[maxn][maxn], Vst[maxm], Match[maxm], flag[2][maxm], Use[maxm];
  15. inline bool Search(int x) {
  16. Vst[x] = 1;
  17. for(register int y = 1; y <= n; ++y)
  18. if(mapp[x][y] && (!Match[y] || (!Vst[Match[y]] && Search(Match[y])))) { Match[y] = x; return 1; }
  19. return 0;
  20. }
  21. inline void Get_Ans(int x) {
  22. flag[1][x] = 1;
  23. for(register int y = 1; y <= n; ++y)
  24. if(mapp[x][y] && Match[y] != x && !flag[0][y]) {
  25. flag[0][y] = 1;
  26. if(Match[y] != 0) Get_Ans(Match[y]);
  27. }
  28. }
  29. int main() {
  30. // freopen("travel.in", "r", stdin);
  31. // freopen("travel.out", "w", stdout);
  32. n = read(), m = read();
  33. for(register int i = 1; i <= m; ++i) {
  34. int u = read(), v = read();
  35. mapp[u][v] = 1;
  36. }
  37. for(register int k = 1; k <= n; ++k)
  38. for(register int i = 1; i <= n; ++i)
  39. for(register int j = 1; j <= n; ++j) mapp[i][j] |= (mapp[i][k] && mapp[k][j]);
  40. for(register int i = 1; i <= n; ++i) {
  41. memset(Vst, 0, sizeof(Vst));
  42. if(Search(i)) Cnt++;
  43. }
  44. printf("%d\n", n - Cnt);
  45. for(register int i = 1; i <= n; ++i) Use[Match[i]] = 1;
  46. for(register int i = 1; i <= n; ++i)
  47. if(!Use[i]) Get_Ans(i);
  48. for(register int i = 1; i <= n; ++i)
  49. if(!flag[1][i] || flag[0][i]) continue;
  50. else printf("%d ", i);
  51. return 0;
  52. }

Summary

一道值得反复思考的好题,用到了很多二分图/网络流的经典结论。

T3 galaxy

Description

Solution

看着很唬人,其实是个简单题。

考虑二操作其实是没限制的,所以 等价。

那么可以把棋盘缩成 的大小,把所有坐标都对 取余。

考虑记录每个点上有多少个棋子,此时只剩下一操作,Hash 下整个棋盘的状态,然记忆化 Search 即可。

注意: 小于 的情况需要特殊判断。

  1. //The Code Is From Dawn
  2. #include<bits/stdc++.h>
  3. #define int long long
  4. using namespace std;
  5. inline int read() {
  6. int x = 0;
  7. char c = getchar();
  8. bool f = 0;
  9. while(!isdigit(c)) {
  10. if(c == EOF) return -1;
  11. f |= (c == '-'), c = getchar();
  12. }
  13. while(isdigit(c)) x = (x * 10) + (c ^ 48), c = getchar();
  14. return f ? -x : x;
  15. }
  16. const int maxn = 5;
  17. int K, n, m, Ex, Ey;
  18. map <int, int> Mapp;
  19. int num[maxn][maxn], Maxx[maxn][maxn];
  20. int go[8][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1}};
  21. inline int Hash() {
  22. int tot = 0;
  23. for(register int i = 0; i < 3; ++i)
  24. for(register int j = 0; j < 3; ++j) tot = tot * 11 + num[i][j];
  25. return tot;
  26. }
  27. inline int Search(int now) {
  28. if(now == 1) { return num[Ex][Ey] ? 1 : -1; }
  29. int State = Hash();
  30. if(Mapp[State]) return Mapp[State];
  31. for(register int x = 0; x < 3; ++x)
  32. for(register int y = 0; y < 3; ++y) {
  33. if(!num[x][y]) continue;
  34. for(register int i = 0; i < 8; ++i) {
  35. int nx = (x + go[i][0] + 3) % 3, ny = (y + go[i][1] + 3) % 3;
  36. if(nx < 0 || ny < 0 || nx >= n || ny >= m || !num[nx][ny]) continue;
  37. int Nex_nx = (nx + go[i][0] + 3) % 3, Nex_ny = (ny + go[i][1] + 3) % 3;
  38. if(Nex_nx < 0 || Nex_ny < 0 || Nex_nx > n || Nex_ny > m) continue;
  39. num[Nex_nx][Nex_ny]++, num[nx][ny]--, num[x][y]--;
  40. int tot = Search(now - 1);
  41. num[Nex_nx][Nex_ny]--, num[nx][ny]++, num[x][y]++;
  42. if(tot == 1) return Mapp[State] = 1;
  43. }
  44. }
  45. return Mapp[State] = -1;
  46. }
  47. signed main() {
  48. // freopen("galaxy.in", "r", stdin);
  49. // freopen("galaxy.out", "w", stdout);
  50. while(~(K = read())) {
  51. n = read(), m = read(), Ex = (read() - 1) % 3, Ey = (read() - 1) % 3;
  52. Mapp.clear();
  53. memset(num, 0, sizeof(num)), memset(Maxx, 0, sizeof(Maxx));
  54. for(register int i = 0; i < n; ++i)
  55. for(register int j = 0; j < m; ++j) Maxx[i % 3][j % 3]++;
  56. for(register int i = 1; i <= K; ++i) {
  57. int x = (read() - 1) % 3, y = (read() - 1) % 3;
  58. num[x][y]++;
  59. }
  60. if(n == 1 && m == 3 && Ey == 1) { printf("No\n"); continue; }
  61. if(Search(K) == 1) printf("Yes\n");
  62. else printf("No\n");
  63. }
  64. return 0;
  65. }

Summary

无限制的移动,可以考虑可不可以缩到一个很小的范围之内。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注