[关闭]
@ljt12138 2018-11-17T11:13:11.000000Z 字数 24722 阅读 837

NOI模板补全计划


这是一些luogu/loj/bzoj模板题的代码...

带修莫队:luogu1903

注意更新pre...

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 10005;
  4. int n, m, blk;
  5. struct node {
  6. int l, r, id, ans;
  7. friend bool operator < (const node &a, const node &b)
  8. {
  9. if (a.l/blk == b.l/blk && a.r/blk == b.r/blk) return a.id < b.id;
  10. if (a.l/blk == b.l/blk) return a.r < b.r;
  11. return a.l < b.l;
  12. }
  13. } qy[MAXN];
  14. int qtop = 0;
  15. inline bool cmp(const node &a, const node &b)
  16. { return a.id < b.id; }
  17. int a[MAXN];
  18. int T[MAXN*100];
  19. int pos[MAXN], dt[MAXN], id[MAXN], pre[MAXN], mtop = 0, top = 0;
  20. int main()
  21. {
  22. scanf("%d%d", &n, &m);
  23. for (int i = 1; i <= n; i++)
  24. scanf("%d", &a[i]);
  25. blk = pow(n, 2.0/3.0);
  26. for (int i = 1; i <= m; i++) {
  27. char c;
  28. int aa, b;
  29. scanf("\n%c %d%d", &c, &aa, &b);
  30. if (c == 'Q') qy[++qtop] = (node){aa, b, i, 0};
  31. else pos[++mtop] = aa, pre[mtop] = a[aa], dt[mtop] = b, id[mtop] = i;
  32. }
  33. sort(qy+1, qy+qtop+1);
  34. int L = 1, R = 0, Ans = 0;
  35. memset(T, 0, sizeof T);
  36. for (int i = 1; i <= qtop; i++) {
  37. while (R < qy[i].r) R++, T[a[R]]++, Ans += (T[a[R]] == 1);
  38. while (L > qy[i].l) L--, T[a[L]]++, Ans += (T[a[L]] == 1);
  39. while (L < qy[i].l) T[a[L]]--, Ans -= (T[a[L]] == 0), L++;
  40. while (R > qy[i].r) T[a[R]]--, Ans -= (T[a[R]] == 0), R--;
  41. while (top+1 <= mtop && id[top+1] <= qy[i].id) {
  42. top++;
  43. if (a[pos[top]] != dt[top]) {
  44. pre[top] = a[pos[top]];
  45. if (pos[top] >= L && pos[top] <= R) {
  46. T[a[pos[top]]]--, T[dt[top]]++;
  47. Ans -= (T[a[pos[top]]] == 0), Ans += (T[dt[top]] == 1);
  48. }
  49. a[pos[top]] = dt[top];
  50. }
  51. }
  52. while (id[top] > qy[i].id) {
  53. if (a[pos[top]] != pre[top]) {
  54. if (pos[top] >= L && pos[top] <= R) {
  55. T[a[pos[top]]]--, T[pre[top]]++;
  56. Ans -= (T[a[pos[top]]] == 0), Ans += (T[pre[top]] == 1);
  57. }
  58. a[pos[top]] = pre[top];
  59. }
  60. top--;
  61. }
  62. qy[i].ans = Ans;
  63. }
  64. sort(qy+1, qy+qtop+1, cmp);
  65. for (int i = 1; i <= qtop; i++)
  66. printf("%d\n", qy[i].ans);
  67. return 0;
  68. }

FFT(NTT) luogu1919

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 200005;
  4. const int mod = 998244353, g = 3;
  5. int A[MAXN], B[MAXN], C[MAXN];
  6. int n, m;
  7. int rev[MAXN];
  8. int power(int a, int n)
  9. {
  10. int ans = 1;
  11. for (int i = 0; i <= 30; i++) {
  12. if (n&(1<<i)) ans = (long long)ans*a%mod;
  13. a = (long long)a*a%mod;
  14. }
  15. return ans;
  16. }
  17. inline int inv(int n)
  18. { return power(n, mod-2); }
  19. void NTT(int A[], int n, int flag)
  20. {
  21. int lgn = int(log2(n)+0.1);
  22. rev[0] = 0;
  23. for (int i = 1; i < n; i++) rev[i] = (rev[i>>1]>>1)|((i&1)<<(lgn-1));
  24. for (int i = 0; i < n; i++)
  25. if (rev[i] < i)
  26. swap(A[i], A[rev[i]]);
  27. for (int k = 2; k <= n; k <<= 1) {
  28. int dw = power(g, (mod-1)/k);
  29. if (flag == -1) dw = inv(dw);
  30. for (int i = 0; i < n; i += k) {
  31. int w = 1, u, t;
  32. for (int j = 0; j < k>>1; j++) {
  33. u = A[i+j], t = (long long)w*A[i+j+(k>>1)]%mod;
  34. A[i+j] = (u+t)%mod, A[i+j+(k>>1)] = ((u-t)%mod+mod)%mod;
  35. w = (long long)w*dw%mod;
  36. }
  37. }
  38. }
  39. if (flag == -1) {
  40. int invn = inv(n);
  41. for (int i = 0; i < n; i++)
  42. A[i] = (long long)A[i]*invn%mod;
  43. }
  44. }
  45. char str[MAXN];
  46. int main()
  47. {
  48. scanf("%d", &n);
  49. scanf("%s", str);
  50. for (int i = 0; i < n; i++) A[i] = str[n-i-1]-'0';
  51. scanf("%s", str);
  52. for (int i = 0; i < n; i++) B[i] = str[n-i-1]-'0';
  53. int m = 1;
  54. while (m < n*2) m <<= 1;
  55. NTT(A, m, 1), NTT(B, m, 1);
  56. for (int i = 0; i < m; i++) C[i] = (long long)A[i]*B[i]%mod;
  57. NTT(C, m, -1);
  58. for (int i = 0; i < m-1; i++) {
  59. C[i+1] += C[i]/10;
  60. C[i] %= 10;
  61. }
  62. int k = m-1;
  63. while (C[k] == 0) k--;
  64. for (int i = k; i >= 0; i--)
  65. printf("%d", C[i]);
  66. puts("");
  67. return 0;
  68. }

点分治:luogu2634

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 20005;
  4. struct node {
  5. int to, next, dis;
  6. } edge[MAXN*2];
  7. int head[MAXN], top = 0;
  8. inline void push(int i, int j, int d)
  9. { edge[++top] = (node) {j, head[i], d}, head[i] = top; }
  10. int vis[MAXN], siz[MAXN];
  11. int num[3];
  12. long long ans = 0;
  13. int n;
  14. void dfs_siz(int nd, int f)
  15. {
  16. siz[nd] = 1;
  17. for (int i = head[nd]; i; i = edge[i].next) {
  18. int to = edge[i].to;
  19. if (to == f || vis[to]) continue;
  20. dfs_siz(to, nd), siz[nd] += siz[to];
  21. }
  22. }
  23. void find_center(int nd, int f, const int tot_siz, int &cnt, int &ans)
  24. {
  25. int maxs = tot_siz-siz[nd];
  26. for (int i = head[nd]; i; i = edge[i].next) {
  27. int to = edge[i].to;
  28. if (to == f || vis[to]) continue;
  29. find_center(to, nd, tot_siz, cnt, ans);
  30. maxs = max(maxs, siz[to]);
  31. }
  32. if (maxs < cnt) cnt = maxs, ans = nd;
  33. }
  34. void dfs_calc(int nd, int f, int dt)
  35. {
  36. ans += num[(3-dt)%3]*2;
  37. for (int i = head[nd]; i; i = edge[i].next) {
  38. int to = edge[i].to;
  39. if (to == f || vis[to]) continue;
  40. dfs_calc(to, nd, (dt+edge[i].dis)%3);
  41. }
  42. }
  43. void dfs_paint(int nd, int f, int dt)
  44. {
  45. num[dt]++;
  46. for (int i = head[nd]; i; i = edge[i].next) {
  47. int to = edge[i].to;
  48. if (to == f || vis[to]) continue;
  49. dfs_paint(to, nd, (dt+edge[i].dis)%3);
  50. }
  51. }
  52. void calc(int nd)
  53. {
  54. dfs_siz(nd, 0);
  55. int cnt = INT_MAX, center = 0;
  56. find_center(nd, 0, siz[nd], cnt, center);
  57. vis[center] = 1, ans++, num[0]++;
  58. for (int i = head[center]; i; i = edge[i].next) {
  59. int to = edge[i].to, d = edge[i].dis;
  60. if (vis[to]) continue;
  61. dfs_calc(to, center, d%3);
  62. dfs_paint(to, center, d%3);
  63. }
  64. num[0] = num[1] = num[2] = 0;
  65. for (int i = head[center]; i; i = edge[i].next) {
  66. int to = edge[i].to;
  67. if (!vis[to]) calc(to);
  68. }
  69. }
  70. inline long long gcd(long long a, long long b)
  71. { return b == 0 ? a : gcd(b, a%b); }
  72. int main()
  73. {
  74. scanf("%d", &n);
  75. for (int i = 1; i < n; i++) {
  76. int u, v, d;
  77. scanf("%d%d%d", &u, &v, &d);
  78. push(u, v, d), push(v, u, d);
  79. }
  80. calc(1);
  81. long long tot = (long long)n*n;
  82. long long c = gcd(ans, tot);
  83. cout << ans/c << "/" << tot/c << endl;
  84. return 0;
  85. }

Tarjan LCA(luogu3379)

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 500005;
  4. struct node {
  5. int to, next;
  6. } edge[MAXN*2];
  7. int head[MAXN], top = 0;
  8. inline void push(int i, int j)
  9. { edge[++top] = (node) {j, head[i]}, head[i] = top; }
  10. int n, m, S, u, v;
  11. vector<pair<int,int> > vec[MAXN];
  12. int fa[MAXN], vis[MAXN], ans[MAXN];
  13. inline int findf(int nd)
  14. { return fa[nd]?fa[nd]=findf(fa[nd]):nd; }
  15. void tarjan(int nd, int f)
  16. {
  17. vis[nd] = 1;
  18. for (int i = 0; i < vec[nd].size(); i++) {
  19. int to = vec[nd][i].first, id = vec[nd][i].second;
  20. if (vis[to]) ans[id] = findf(to);
  21. }
  22. for (int i = head[nd]; i; i = edge[i].next) {
  23. int to = edge[i].to;
  24. if (to == f) continue;
  25. tarjan(to, nd);
  26. }
  27. fa[nd] = f;
  28. }
  29. int main()
  30. {
  31. scanf("%d%d%d", &n, &m, &S);
  32. for (int i = 1; i < n; i++) {
  33. scanf("%d%d", &u, &v);
  34. push(u, v), push(v, u);
  35. }
  36. for (int i = 1; i <= m; i++) {
  37. scanf("%d%d", &u, &v);
  38. vec[u].push_back(make_pair(v, i)), vec[v].push_back(make_pair(u, i));
  39. }
  40. tarjan(S, 0);
  41. for (int i = 1; i <= m; i++)
  42. printf("%d\n", ans[i]);
  43. return 0;
  44. }

可并堆:luogu3377

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 100005;
  4. struct node {
  5. pair<int, int> dat;
  6. int lc, rc;
  7. node()
  8. { lc = rc = 0; }
  9. } hp[MAXN];
  10. int merge(int a, int b)
  11. {
  12. if (a == 0 || b == 0) return a+b;
  13. if (hp[a].dat > hp[b].dat) swap(a, b);
  14. hp[a].lc = merge(hp[a].lc, b);
  15. swap(hp[a].lc, hp[a].rc);
  16. return a;
  17. }
  18. pair<int,int> pop(int &a)
  19. {
  20. pair<int, int> ans = hp[a].dat;
  21. a = merge(hp[a].lc, hp[a].rc);
  22. return ans;
  23. }
  24. int del[MAXN], fa[MAXN], tree[MAXN];
  25. inline int findf(int nd)
  26. { return fa[nd]?fa[nd]=findf(fa[nd]):nd; }
  27. int n, m, u;
  28. int main()
  29. {
  30. scanf("%d%d", &n, &m);
  31. for (int i = 1; i <= n; i++) {
  32. scanf("%d", &u);
  33. hp[i].dat = make_pair(u, i);
  34. tree[i] = i;
  35. }
  36. int opt, x, y;
  37. for (int i = 1; i <= m; i++) {
  38. scanf("%d", &opt);
  39. if (opt == 1) {
  40. scanf("%d%d", &x, &y);
  41. if (del[x] || del[y] || findf(x) == findf(y)) continue;
  42. x = findf(x), y = findf(y);
  43. fa[x] = y, tree[y] = merge(tree[x], tree[y]);
  44. } else {
  45. scanf("%d", &x);
  46. if (del[x]) puts("-1");
  47. else {
  48. x = findf(x);
  49. pair<int, int> ans = pop(tree[x]);
  50. del[ans.second] = 1;
  51. printf("%d\n", ans.first);
  52. }
  53. }
  54. }
  55. return 0;
  56. }

LCT: luogu3690

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 300005;
  4. int chl[MAXN][2], fa[MAXN], dat[MAXN], sum[MAXN], rev[MAXN];
  5. int stk[MAXN], top;
  6. inline bool is_rt(int x)
  7. { return chl[fa[x]][0] != x && chl[fa[x]][1] != x; }
  8. inline void pdw(int nd)
  9. {
  10. if (chl[nd][0]) rev[chl[nd][0]] ^= rev[nd];
  11. if (chl[nd][1]) rev[chl[nd][1]] ^= rev[nd];
  12. if (rev[nd]) swap(chl[nd][0], chl[nd][1]), rev[nd] = 0;
  13. }
  14. inline void update(int nd)
  15. { sum[nd] = dat[nd]^sum[chl[nd][0]]^sum[chl[nd][1]]; }
  16. void zig(int nd)
  17. {
  18. int p = fa[nd], g = fa[p], tp = chl[p][0] != nd, tg = chl[g][0] != p;
  19. int son = chl[nd][tp^1];
  20. if (son) fa[son] = p;
  21. if (!is_rt(p)) chl[g][tg] = nd;
  22. fa[p] = nd, fa[nd] = g, chl[nd][tp^1] = p, chl[p][tp] = son;
  23. update(p), update(nd);
  24. }
  25. void splay(int nd)
  26. {
  27. stk[top = 1] = nd;
  28. for (int i = nd; !is_rt(i); i = fa[i]) stk[++top] = fa[i];
  29. while (top) pdw(stk[top--]);
  30. while (!is_rt(nd)) {
  31. int p = fa[nd], g = fa[p], tp = chl[p][0] != nd, tg = chl[g][0] != p;
  32. if (is_rt(p)) { zig(nd); break; }
  33. else if (tp == tg) zig(p), zig(nd);
  34. else zig(nd), zig(nd);
  35. }
  36. }
  37. void access(int x)
  38. {
  39. for (int y = 0; x; x = fa[y = x])
  40. splay(x), chl[x][1] = y, update(x);
  41. }
  42. void make_rt(int x)
  43. {
  44. access(x), splay(x), rev[x] ^= 1;
  45. }
  46. inline void link(int x, int y)
  47. { make_rt(x), fa[x] = y, access(x); }
  48. inline void cut(int x, int y)
  49. {
  50. make_rt(x), access(y), splay(y);
  51. if (chl[y][0] != x) return;
  52. chl[y][0] = fa[x] = 0;
  53. update(y);
  54. }
  55. int findf(int x)
  56. {
  57. access(x), splay(x);
  58. while (chl[x][0]) x = chl[x][0];
  59. return x;
  60. }
  61. int query(int x, int y)
  62. {
  63. make_rt(x), access(y), splay(y);
  64. return sum[chl[y][0]]^dat[y];
  65. }
  66. void modify(int x, int y)
  67. {
  68. access(x), splay(x), dat[x] = y, update(x);
  69. }
  70. int n, m;
  71. inline int read()
  72. {
  73. int a = 0, c;
  74. do c = getchar(); while (!isdigit(c));
  75. while (isdigit(c)) {
  76. a = a*10+c-'0';
  77. c = getchar();
  78. }
  79. return a;
  80. }
  81. int main()
  82. {
  83. n = read(), m = read();
  84. for (int i = 1; i <= n; i++)
  85. dat[i] = read();
  86. int opt, x, y;
  87. for (int i = 1; i <= m; i++) {
  88. opt = read(), x = read(), y = read();
  89. if (opt == 0) {
  90. printf("%d\n", query(x, y));
  91. } else if (opt == 1) {
  92. int a = findf(x), b = findf(y);
  93. if (a == b) continue;
  94. link(x, y);
  95. } else if (opt == 2) {
  96. cut(x, y);
  97. } else {
  98. modify(x, y);
  99. }
  100. }
  101. return 0;
  102. }

tarjan求割点: luogu3388

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 100005;
  4. struct node {
  5. int to, next;
  6. } edge[MAXN*2];
  7. int head[MAXN], top = 0;
  8. inline void push(int i, int j)
  9. { edge[++top] = (node) {j, head[i]}, head[i] = top; }
  10. int dfn[MAXN], low[MAXN], dfn_top = 0;
  11. int cur[MAXN];
  12. int n, m;
  13. void tarjan(int nd, int f)
  14. {
  15. // cerr << f << "-->" << nd << endl;
  16. dfn[nd] = ++dfn_top, low[nd] = dfn[nd];
  17. int cnt = 0;
  18. for (int i = head[nd]; i; i = edge[i].next) {
  19. int to = edge[i].to;
  20. if (to == f) continue;
  21. if (dfn[to]) low[nd] = min(low[nd], dfn[to]);
  22. else {
  23. cnt++, tarjan(to, nd), low[nd] = min(low[nd], low[to]);
  24. if (f && low[to] >= dfn[nd]) cur[nd] = 1;
  25. }
  26. }
  27. if (!f && cnt >= 2) cur[nd] = 1;
  28. }
  29. int main()
  30. {
  31. scanf("%d%d", &n, &m);
  32. for (int i = 1; i <= m; i++) {
  33. int u, v;
  34. scanf("%d%d", &u, &v);
  35. push(u, v), push(v, u);
  36. }
  37. for (int i = 1; i <= n; i++)
  38. if (!dfn[i])
  39. tarjan(i, 0);
  40. int cnt = 0;
  41. for (int i = 1; i <= n; i++)
  42. if (cur[i])
  43. cnt++;
  44. printf("%d\n", cnt);
  45. for (int i = 1; i <= n; i++)
  46. if (cur[i])
  47. printf("%d ", i);
  48. puts("");
  49. return 0;
  50. }

AC自动机 luogu3796

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 20005;
  4. int chl[MAXN][26], fail[MAXN], top = 0, root = 0;
  5. int vis[MAXN];
  6. struct node {
  7. int to, next;
  8. } edge[MAXN*2];
  9. int head[MAXN], top_tp = 0;
  10. inline void push(int i, int j)
  11. { edge[++top_tp] = (node) {j, head[i]}, head[i] = top_tp; }
  12. int pos[MAXN];
  13. inline void push(int &nd, const char *str, int id)
  14. {
  15. if (!nd) nd = ++top;
  16. if (*str != '\0') push(chl[nd][*str-'a'], str+1, id);
  17. else pos[id] = nd;
  18. }
  19. queue<int> que;
  20. void build()
  21. {
  22. int nd = root; que.push(nd);
  23. while (!que.empty()) {
  24. int nd = que.front(); que.pop();
  25. for (int i = 0; i < 26; i++) {
  26. if (!chl[nd][i]) continue;
  27. int p = fail[nd];
  28. while (p && !chl[p][i]) p = fail[p];
  29. if (!p) fail[chl[nd][i]] = root;
  30. else fail[chl[nd][i]] = chl[p][i];
  31. que.push(chl[nd][i]);
  32. }
  33. }
  34. for (int i = 2; i <= top; i++) push(fail[i], i);
  35. }
  36. void match(char *str)
  37. {
  38. int nd = root;
  39. for (char *p = str; *p != '\0'; ++p) {
  40. while (nd && !chl[nd][*p-'a']) nd = fail[nd];
  41. if (!nd) nd = root;
  42. else { nd = chl[nd][*p-'a'], vis[nd]++; }
  43. }
  44. }
  45. void display(int nd, int tab, char from)
  46. {
  47. if (!nd) return;
  48. for (int i = 1; i <= tab; i++) putchar(' ');
  49. printf("--%c--> %d, fail = %d, vis = %d\n", from, nd, fail[nd], vis[nd]);
  50. for (int i = 0; i < 26; i++) {
  51. if (chl[nd][i]) display(chl[nd][i], tab+2, i+'a');
  52. }
  53. }
  54. void dfs1(int nd)
  55. {
  56. for (int i = head[nd]; i; i = edge[i].next) {
  57. int to = edge[i].to;
  58. dfs1(to), vis[nd] += vis[to];
  59. }
  60. }
  61. char str[151][75];
  62. int n;
  63. char s[1000005];
  64. int main()
  65. {
  66. while (scanf("%d", &n)) {
  67. if (n == 0) break;
  68. root = top = top_tp = 0;
  69. memset(head, 0, sizeof head), memset(chl, 0, sizeof chl), memset(fail, 0, sizeof fail);
  70. memset(vis, 0, sizeof vis);
  71. for (int i = 1; i <= n; i++) scanf("%s", str[i]), push(root, str[i], i);
  72. scanf("%s", s);
  73. build();
  74. match(s);
  75. dfs1(root);
  76. int max_val = 0;
  77. for (int i = 1; i <= n; i++) {
  78. max_val = max(max_val, vis[pos[i]]);
  79. }
  80. printf("%d\n", max_val);
  81. for (int i = 1; i <= n; i++)
  82. if (vis[pos[i]] == max_val)
  83. puts(str[i]);
  84. }
  85. return 0;
  86. }

匈牙利算法 luogu3386

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 1005;
  4. int n, m, e, u, v;
  5. inline int read()
  6. {
  7. int a = 0, c;
  8. do c = getchar(); while (!isdigit(c));
  9. while (isdigit(c)) {
  10. a = a*10+c-'0';
  11. c = getchar();
  12. }
  13. return a;
  14. }
  15. struct node {
  16. int to, next;
  17. } edge[MAXN*MAXN];
  18. int head[MAXN], top = 0;
  19. inline void push(int i, int j)
  20. { edge[++top] = (node) {j, head[i]}, head[i] = top; }
  21. int link[MAXN], vis[MAXN];
  22. int s[MAXN];
  23. bool arg(int nd)
  24. {
  25. for (int i = head[nd]; i; i = edge[i].next) {
  26. int to = edge[i].to;
  27. if (vis[to]) continue;
  28. vis[to] = 1;
  29. if (!link[to] || arg(link[to])) {
  30. link[to] = nd;
  31. s[nd] = 1;
  32. return 1;
  33. }
  34. }
  35. return 0;
  36. }
  37. void match()
  38. {
  39. int cnt = 0;
  40. for (int i = 1; i <= n; i++) {
  41. memset(vis, 0, sizeof vis);
  42. if (!s[i] && arg(i)) cnt++;
  43. }
  44. printf("%d\n", cnt);
  45. }
  46. int main()
  47. {
  48. n = read(), m = read(), e = read();
  49. for (int i = 1; i <= e; i++) {
  50. u = read(), v = read();
  51. if (u > n || v > m) continue;
  52. push(u, v);
  53. }
  54. match();
  55. return 0;
  56. }

高斯消元法 luogu3389

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 105;
  4. double A[MAXN][MAXN];
  5. int n;
  6. void solve()
  7. {
  8. for (int i = 1; i <= n; i++) {
  9. int pos = i;
  10. while (pos <= n && A[pos][i] == 0) pos++;
  11. if (pos > n) {
  12. puts("No Solution");
  13. return;
  14. }
  15. swap(A[pos], A[i]);
  16. for (int j = 1; j <= n; j++) {
  17. if (j == i) continue;
  18. double tmp = -A[j][i]/A[i][i];
  19. for (int k = 1; k <= n+1; k++)
  20. A[j][k] += A[i][k]*tmp;
  21. }
  22. }
  23. for (int i = 1; i <= n; i++)
  24. printf("%.2f\n", A[i][n+1]/A[i][i]);
  25. }
  26. int main()
  27. {
  28. scanf("%d", &n);
  29. for (int i = 1; i <= n; i++)
  30. for (int j = 1; j <= n+1; j++)
  31. scanf("%lf", &A[i][j]);
  32. solve();
  33. return 0;
  34. }

CRT:SDOI2010古代猪文

和拉格朗日插值法类似,就是构造一个方程满足所有方程组。考虑。设为满足的数,,则可以构造:

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int mod = 999911659;
  4. const int a[] = {2, 3, 4679, 35617}, M = mod-1;
  5. int power(int a, int b, int mod)
  6. {
  7. int ans = 1;
  8. for (int i = 0; i <= 30; i++) {
  9. if ((b>>i)&1) ans = (long long)ans*a%mod;
  10. a = (long long)a*a%mod;
  11. }
  12. return ans;
  13. }
  14. inline int gcd(int a, int b)
  15. { return b==0?a:gcd(b, a%b); }
  16. int ext_gcd(int a, int b, int &x, int &y)
  17. {
  18. if (b == 0) {
  19. x = 1, y = 0;
  20. return a;
  21. }
  22. int ans = ext_gcd(b, a%b, y, x);
  23. y = y-a/b*x;
  24. return ans;
  25. }
  26. int inv(int a, int m) // (a, b) = 1
  27. {
  28. int x, y;
  29. ext_gcd(a, m, x, y);
  30. return (x%m+m)%m;
  31. }
  32. int fac[4][40005], ifac[4][40005];
  33. inline int choose(int n, int m, int mod_id)
  34. {
  35. if (n < m) return 0;
  36. return (long long)fac[mod_id][n]*ifac[mod_id][m]%a[mod_id]*ifac[mod_id][n-m]%a[mod_id];
  37. }
  38. inline int lucas(int n, int m, int mod_id)
  39. {
  40. if (n < a[mod_id]) return choose(n, m, mod_id);
  41. return (long long)lucas(n/a[mod_id], m/a[mod_id], mod_id)*choose(n%a[mod_id], m%a[mod_id], mod_id)%a[mod_id];
  42. }
  43. inline int choose_mod(int n, int m)
  44. {
  45. int ans[4], x = 0;
  46. // cerr << n << " " << m << endl;
  47. for (int i = 0; i < 4; i++) {
  48. ans[i] = lucas(n, m, i);
  49. // cerr << ans[i] << " ";
  50. }
  51. // cerr << endl;
  52. for (int i = 0; i < 4; i++) x = (x+(long long)M/a[i]*inv(M/a[i]%a[i], a[i])%M*ans[i]%M)%M;
  53. // cerr << x << endl;
  54. return x;
  55. }
  56. int n, g;
  57. int main()
  58. {
  59. scanf("%d%d", &n, &g);
  60. if (g%mod == 0) {
  61. puts("0");
  62. return 0;
  63. }
  64. for (int i = 0; i < 4; i++) fac[i][0] = ifac[i][0] = 1;
  65. for (int i = 0; i < 4; i++) {
  66. for (int j = 1; j < a[i]; j++)
  67. fac[i][j] = (long long)fac[i][j-1]*j%a[i];
  68. for (int j = 1; j < a[i]; j++)
  69. ifac[i][j] = (long long)ifac[i][j-1]*inv(j, a[i])%a[i];
  70. }
  71. // cerr << lucas(4, 1, 0) << endl;
  72. int ans = 0;
  73. for (int i = 1; i*i <= n; i++)
  74. if (n%i == 0) {
  75. ans = (ans+choose_mod(n, i))%M;
  76. if (n/i > i) ans = (ans+choose_mod(n, n/i))%M;
  77. }
  78. printf("%d\n", power(g, ans, mod));
  79. return 0;
  80. }

拉格朗日插值法

次多项式满足,则满足:

SAM:线段树合并/set启发式合并

2780: [Spoj]8093 Sevenk Love Oimaster

题意:给定若干个模式串,多组询问,问有多少个模式串包含作为其子串。

对模式串建立广义后缀自动机。对于每一个模式串,找到他所有前缀的状态并在其集合中加入。这样,对于一个询问,先找到他的位置,然后答案就是其子树中set并的大小。可以用平衡树/启发式合并,或者线段树合并来维护。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 100005;
  4. struct SAM {
  5. int chl[MAXN][26], top, root, fa[MAXN], maxl[MAXN];
  6. set<int> right_set[MAXN];
  7. int pos[MAXN];
  8. int dp[MAXN];
  9. struct node {
  10. int to, next;
  11. } edge[MAXN];
  12. int head[MAXN], top_tp;
  13. inline void push_edge(int i, int j)
  14. { edge[++top_tp] = (node) {j, head[i]}, head[i] = top_tp; }
  15. void clear()
  16. {
  17. memset(chl, 0, sizeof chl), top_tp = top = root = 1;
  18. memset(fa, 0, sizeof fa), memset(maxl, 0, sizeof maxl);
  19. }
  20. SAM()
  21. { clear(); }
  22. int push(int nd, int x)
  23. {
  24. int p = nd, np = ++top; maxl[np] = maxl[p]+1;
  25. while (p && !chl[p][x]) chl[p][x] = np, p = fa[p];
  26. if (!p) fa[np] = root;
  27. else {
  28. int q = chl[p][x];
  29. if (maxl[q] == maxl[p]+1) fa[np] = q;
  30. else {
  31. int nq = ++top; maxl[nq] = maxl[p]+1, memcpy(chl[nq], chl[q], sizeof chl[q]);
  32. fa[nq] = fa[q], fa[q] = fa[np] = nq;
  33. while (p && chl[p][x] == q) chl[p][x] = nq, p = fa[p];
  34. }
  35. }
  36. return np;
  37. }
  38. int get_pos(char *str)
  39. {
  40. int nd = root;
  41. for (char *p = str; *p != '\0'; ++p) {
  42. if (!chl[nd][*p-'a']) return -1;
  43. nd = chl[nd][*p-'a'];
  44. }
  45. return nd;
  46. }
  47. int merge(int a, int b)
  48. {
  49. if (right_set[a].size() < right_set[b].size()) swap(a, b);
  50. for (set<int>::iterator j = right_set[b].begin(); j != right_set[b].end(); ++j)
  51. right_set[a].insert(*j);
  52. return a;
  53. }
  54. void dfs(int nd)
  55. {
  56. for (int i = head[nd]; i; i = edge[i].next) {
  57. int to = edge[i].to;
  58. dfs(to);
  59. }
  60. for (int i = head[nd]; i; i = edge[i].next) {
  61. int to = edge[i].to;
  62. pos[nd] = merge(pos[nd], pos[to]);
  63. }
  64. dp[nd] = right_set[pos[nd]].size();
  65. }
  66. inline void get_ans()
  67. {
  68. for (int i = 1; i <= top; i++) {
  69. pos[i] = i;
  70. if (fa[i]) push_edge(fa[i], i);
  71. }
  72. dfs(root);
  73. }
  74. };
  75. struct trie {
  76. int chl[MAXN][26], fa[MAXN], stat[MAXN], top, root;
  77. SAM sam;
  78. int fin[MAXN], fin_top;
  79. void clear()
  80. {
  81. sam.clear(), fin_top = top = root = 0;
  82. memset(stat, 0, sizeof stat);
  83. }
  84. trie()
  85. { clear(); }
  86. inline void push(int &nd, const char *str)
  87. {
  88. if (!nd) nd = ++top;
  89. if (*str != '\0') push(chl[nd][*str-'a'], str+1), fa[chl[nd][*str-'a']] = nd;
  90. else fin[++fin_top] = nd;
  91. }
  92. inline void push(const char *str)
  93. { push(root, str); }
  94. queue<int> que;
  95. void build_sam()
  96. {
  97. stat[root] = sam.root, que.push(root);
  98. while (!que.empty()) {
  99. int nd = que.front(); que.pop();
  100. for (int i = 0; i < 26; i++) {
  101. if (!chl[nd][i]) continue;
  102. stat[chl[nd][i]] = sam.push(stat[nd], i);
  103. que.push(chl[nd][i]);
  104. }
  105. }
  106. }
  107. void paint()
  108. {
  109. for (int i = 1; i <= fin_top; i++) {
  110. for (register int j = fin[i]; j; j = fa[j])
  111. sam.right_set[stat[j]].insert(i);
  112. }
  113. }
  114. } T;
  115. int n, q;
  116. char s[400005];
  117. int pos[60005];
  118. int main()
  119. {
  120. scanf("%d%d", &n, &q);
  121. for (int i = 1; i <= n; i++) {
  122. scanf("%s", s);
  123. T.push(s);
  124. }
  125. T.build_sam();
  126. T.paint();
  127. for (int i = 1; i <= q; i++) {
  128. scanf("%s", s);
  129. pos[i] = T.sam.get_pos(s);
  130. }
  131. T.sam.get_ans();
  132. for (int i = 1; i <= q; i++) {
  133. if (pos[i] == -1) puts("0");
  134. else printf("%d\n", T.sam.dp[pos[i]]);
  135. }
  136. return 0;
  137. }

树套树 二逼平衡树

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 8000005, N = 50005;
  4. int chl[MAXN][2], fa[MAXN], top = 0;
  5. int dat[MAXN];
  6. int root[N];
  7. int siz[MAXN];
  8. void update(int nd)
  9. { siz[nd] = (chl[nd][0]!=0)*siz[chl[nd][0]]+(chl[nd][1]!=0)*siz[chl[nd][1]]+1; }
  10. void zig(int nd, int id)
  11. {
  12. int p = fa[nd], g = fa[p], tp = chl[p][0] != nd, tg = chl[g][0] != p;
  13. int son = chl[nd][tp^1];
  14. if (son) fa[son] = p;
  15. if (g) chl[g][tg] = nd;
  16. else root[id] = nd;
  17. fa[p] = nd, fa[nd] = g, chl[nd][tp^1] = p, chl[p][tp] = son;
  18. update(p), update(nd);
  19. }
  20. void splay(int nd, int id, int tar = 0)
  21. {
  22. while (fa[nd] != tar) {
  23. // cerr << nd << " " << fa[nd] << endl;
  24. int p = fa[nd], g = fa[p], tp = chl[p][0] != nd, tg = chl[g][0] != p;
  25. if (g == tar) { zig(nd, id); break; }
  26. else if (tp == tg) zig(p, id), zig(nd, id);
  27. else zig(nd, id), zig(nd, id);
  28. }
  29. }
  30. int get_rank(int nd, int id)
  31. {
  32. splay(nd, id);
  33. return chl[nd][0]+1;
  34. }
  35. int number_ls(int k, int id)
  36. {
  37. int ans = 0, nd = root[id];
  38. while (nd) {
  39. if (dat[nd] < k) ans += siz[chl[nd][0]]+1, nd = chl[nd][1];
  40. else nd = chl[nd][0];
  41. }
  42. return ans;
  43. }
  44. int number_le(int k, int id)
  45. {
  46. int ans = 0, nd = root[id];
  47. while (nd) {
  48. if (dat[nd] <= k) ans += siz[chl[nd][0]]+1, nd = chl[nd][1];
  49. else nd = chl[nd][0];
  50. }
  51. return ans;
  52. }
  53. int find_kth(int k, int id)
  54. {
  55. int nd = root[id];
  56. while (1) {
  57. if (siz[chl[nd][0]]+1 == k) break;
  58. else if (siz[chl[nd][0]]+1 > k) nd = chl[nd][0];
  59. else k -= siz[chl[nd][0]]+1, nd = chl[nd][1];
  60. }
  61. splay(nd, id);
  62. return nd;
  63. }
  64. int pre_ele(int dt, int id)
  65. {
  66. int ls = number_ls(dt, id);
  67. if (ls == 0) return 0;
  68. return find_kth(ls, id);
  69. }
  70. int nxt_ele(int dt, int id)
  71. {
  72. int gt = number_le(dt, id)+1;
  73. if (gt > siz[root[id]]) return 0;
  74. return find_kth(gt, id);
  75. }
  76. int push(int &nd, int dt, int f = 0)
  77. {
  78. if (nd == 0) {
  79. nd = ++top, dat[nd] = dt, update(nd);
  80. fa[nd] = f;
  81. return top;
  82. }
  83. siz[nd]++;
  84. if (dt <= dat[nd]) return push(chl[nd][0], dt, nd);
  85. else return push(chl[nd][1], dt, nd);
  86. }
  87. int pop_ele(int dt, int id)
  88. {
  89. // printf("pop %d ---> %d\n", dt, id);
  90. int num = number_ls(dt, id)+1;
  91. // cerr << id << "j" << num << endl;
  92. int pre = find_kth(num-1, id), nxt = find_kth(num+1, id);
  93. // cerr << pre << " " << nxt << endl;
  94. // cerr << dat[nxt] << " " << dat[pre] << endl;
  95. splay(pre, id), splay(nxt, id, pre);
  96. chl[nxt][0] = 0, update(nxt), update(pre);
  97. // puts("---");
  98. }
  99. void push_ele(int dt, int id)
  100. {
  101. // printf("push %d --> %d\n", dt, id);
  102. int nd = push(root[id], dt);
  103. splay(nd, id);
  104. }
  105. void display(int nd, int tab)
  106. {
  107. if (!nd) return;
  108. for (int i = 1; i <= tab; i++) putchar(' ');
  109. printf("siz = %d, dat = %d\n", siz[nd], dat[nd]);
  110. display(chl[nd][0], tab+2), display(chl[nd][1], tab+2);
  111. }
  112. int c[N], a[N], n, m;
  113. inline int lowbit(int i)
  114. { return i&(-i); }
  115. void del(int nd, int dt)
  116. {
  117. for (; nd <= n; nd += lowbit(nd))
  118. pop_ele(dt, nd);
  119. }
  120. void add(int nd, int dt)
  121. {
  122. for (; nd <= n; nd += lowbit(nd))
  123. push_ele(dt, nd);
  124. }
  125. void modify(int nd, int dt)
  126. {
  127. del(nd, a[nd]), add(nd, dt), a[nd] = dt;
  128. }
  129. int number_prefix_ls(int pos, int dt)
  130. {
  131. int ans = 0;
  132. for (; pos; pos -= lowbit(pos))
  133. ans += number_ls(dt, pos)-1;
  134. return ans;
  135. }
  136. int number_seg_ls(int L, int R, int dt)
  137. { return number_prefix_ls(R, dt)-number_prefix_ls(L-1, dt); }
  138. int number_prefix_le(int pos, int dt)
  139. {
  140. int ans = 0;
  141. for (; pos; pos -= lowbit(pos))
  142. ans += number_le(dt, pos)-1;
  143. return ans;
  144. }
  145. int number_seg_le(int L, int R, int dt)
  146. { return number_prefix_le(R, dt)-number_prefix_le(L-1, dt); }
  147. int find_seg_kth(int Lpos, int Rpos, int dt)
  148. {
  149. int L = 0, R = 1e8, Mid;
  150. while (L <= R) {
  151. Mid = (L+R)>>1;
  152. if (number_seg_le(Lpos, Rpos, Mid) >= dt) R = Mid-1;
  153. else L = Mid+1;
  154. }
  155. return R+1;
  156. }
  157. int find_seg_pre(int Lpos, int Rpos, int dt)
  158. {
  159. int num = number_seg_ls(Lpos, Rpos, dt);
  160. if (num == 0) return INT_MIN+1;
  161. return find_seg_kth(Lpos, Rpos, num);
  162. }
  163. int find_seg_nxt(int Lpos, int Rpos, int dt)
  164. {
  165. int num = number_seg_le(Lpos, Rpos, dt)+1;
  166. if (num > Rpos-Lpos+1) return INT_MAX;
  167. return find_seg_kth(Lpos, Rpos, num);
  168. }
  169. inline int read()
  170. {
  171. int a = 0;
  172. scanf("%d", &a);
  173. return a;
  174. }
  175. int main()
  176. {
  177. // freopen("psh.in", "r", stdin);
  178. // freopen("psh.out", "w", stdout);
  179. n = read(), m = read();
  180. for (int i = 1; i <= n; i++) a[i] = read();
  181. for (int i = 1; i <= n; i++)
  182. push_ele(INT_MIN+1, i), push_ele(INT_MAX, i);
  183. for (int i = 1; i <= n; i++)
  184. add(i, a[i]);
  185. int cnt = 0;
  186. for (int i = 1; i <= m; i++) {
  187. int opt, l, r, k;
  188. opt = read();
  189. cnt++;
  190. if (opt == 1) {
  191. l = read(), r = read(), k = read();
  192. printf("%d\n", number_seg_ls(l, r, k)+1);
  193. } else if (opt == 2) {
  194. l = read(), r = read(), k = read();
  195. printf("%d\n", find_seg_kth(l, r, k));
  196. } else if (opt == 3) {
  197. l = read(), r = read();
  198. modify(l, r);
  199. cnt--;
  200. } else if (opt == 4) {
  201. l = read(), r = read(), k = read();
  202. printf("%d\n", find_seg_pre(l, r, k));
  203. } else {
  204. l = read(), r = read(), k = read();
  205. printf("%d\n", find_seg_nxt(l, r, k));
  206. }
  207. }
  208. return 0;
  209. }

Tarjan缩点 HAOI2006受欢迎的牛

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 50005;
  4. struct node {
  5. int to, next;
  6. } edge[MAXN];
  7. int head[MAXN], top = 0;
  8. inline void push(int i, int j)
  9. { edge[++top] = (node) {j, head[i]}, head[i] = top; }
  10. int dfn[MAXN], dfn_top = 0, low[MAXN], vis[MAXN], stk[MAXN], stk_top = 0;
  11. int g[MAXN], gtop = 0, gsiz[MAXN];
  12. int d[MAXN];
  13. int n, m;
  14. void tarjan(int nd)
  15. {
  16. stk[++top] = nd, vis[nd] = 1, dfn[nd] = low[nd] = ++dfn_top;
  17. for (int i = head[nd]; i; i = edge[i].next) {
  18. int to = edge[i].to;
  19. if (!dfn[to]) tarjan(to), low[nd] = min(low[nd], low[to]);
  20. else if (vis[to]) low[nd] = min(low[nd], dfn[to]);
  21. }
  22. if (dfn[nd] == low[nd]) {
  23. gtop++;
  24. int now;
  25. do {
  26. now = stk[top--];
  27. vis[now] = 0; // !!!
  28. g[now] = gtop, gsiz[gtop]++;
  29. } while (now != nd);
  30. }
  31. }
  32. int main()
  33. {
  34. scanf("%d%d", &n, &m);
  35. for (int i = 1; i <= m; i++) {
  36. int u, v;
  37. scanf("%d%d", &u, &v);
  38. push(u, v);
  39. }
  40. for (int i = 1; i <= n; i++)
  41. if (!dfn[i])
  42. tarjan(i);
  43. for (int i = 1; i <= n; i++) {
  44. for (int j = head[i]; j; j = edge[j].next) {
  45. int to = edge[j].to;
  46. d[g[i]] += (g[to] != g[i]);
  47. }
  48. }
  49. int pos = 0, cnt = 0;
  50. for (int i = 1; i <= gtop; i++)
  51. if (d[i] == 0) {
  52. pos = i, cnt++;
  53. }
  54. if (cnt != 1) puts("0");
  55. else printf("%d\n", gsiz[pos]);
  56. return 0;
  57. }

KMP loj103

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 1000005;
  4. char S[MAXN], T[MAXN];
  5. int nxt[MAXN];
  6. int main()
  7. {
  8. scanf("%s", S+1), scanf("%s", T+1);
  9. nxt[1] = 0;
  10. int pL = strlen(T+1), sL = strlen(S+1), cnt = 0;
  11. int p = 0;
  12. for (int i = 2; i <= pL; i++) {
  13. while (p && T[p+1] != T[i]) p = nxt[p];
  14. if (T[p+1] == T[i]) p++;
  15. nxt[i] = p;
  16. }
  17. p = 0;
  18. for (int i = 1; i <= sL; i++) {
  19. while (p && T[p+1] != S[i]) p = nxt[p];
  20. if (T[p+1] == S[i]) p++;
  21. if (p == pL) {
  22. cnt++;
  23. p = nxt[p];
  24. }
  25. }
  26. printf("%d\n", cnt);
  27. return 0;
  28. }

后缀数组 loj111

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 1000005;
  4. struct SA {
  5. struct node {
  6. int k[2], id;
  7. node(){}
  8. node(int x, int y) {k[0] = x, k[1] = y; }
  9. } RE[MAXN], RT[MAXN];
  10. int a[MAXN], sum[MAXN], SA[MAXN], rank[MAXN], n;
  11. void radix_sort()
  12. {
  13. for (int y = 1; y >= 0; y--) {
  14. memset(sum, 0, sizeof sum);
  15. for (int i = 1; i <= n; i++) RT[i] = RE[i];
  16. for (int i = 1; i <= n; i++) sum[RT[i].k[y]]++;
  17. for (int i = 1; i < MAXN; i++) sum[i] += sum[i-1];
  18. for (int i = n; i >= 1; i--) RE[sum[RT[i].k[y]]--] = RT[i];
  19. }
  20. for (int i = 1; i <= n; i++) {
  21. rank[RE[i].id] = rank[RE[i-1].id];
  22. if (RE[i].k[0] != RE[i-1].k[0] || RE[i].k[1] != RE[i-1].k[1])
  23. rank[RE[i].id]++;
  24. }
  25. }
  26. void build_SA()
  27. {
  28. for (int i = 1; i <= n; i++) RE[i] = node(a[i], 0), RE[i].id = i;
  29. radix_sort();
  30. for (int k = 1; k < n; k <<= 1) {
  31. for (int j = 1; j <= n; j++) RE[j] = node(rank[j], j+k<=n?rank[j+k]:0), RE[j].id = j;
  32. radix_sort();
  33. }
  34. for (int i = 1; i <= n; i++)
  35. SA[rank[i]] = i;
  36. }
  37. } sa;
  38. char str[MAXN];
  39. int main()
  40. {
  41. scanf("%s", str+1);
  42. sa.n = strlen(str+1);
  43. for (int i = 1; i <= sa.n; i++) sa.a[i] = str[i];
  44. sa.build_SA();
  45. for (int i = 1; i <= sa.n; i++)
  46. printf("%d ", sa.SA[i]);
  47. puts("");
  48. return 0;
  49. }

线性基k大

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 100005;
  4. int have0 = 0;
  5. struct linear_base {
  6. long long a[70];
  7. int top;
  8. linear_base()
  9. { top = 0; }
  10. void push(long long x)
  11. {
  12. for (int i = 1; i <= top; i++)
  13. if ((x^a[i]) < x)
  14. x ^= a[i];
  15. if (!x) { have0 = 1; return; }
  16. a[++top] = x;
  17. int i = top;
  18. for (; i > 1 && a[i] > a[i-1]; i--)
  19. swap(a[i], a[i-1]);
  20. for (i--; i >= 1; i--)
  21. if ((x^a[i]) < a[i])
  22. a[i] ^= x;
  23. }
  24. } lb;
  25. int main()
  26. {
  27. int n, m;
  28. long long x;
  29. scanf("%d", &n);
  30. for (int i = 1; i <= n; i++) {
  31. scanf("%lld", &x), lb.push(x);
  32. // for (int i = 1; i <= lb.top; i++) cerr << lb.a[i] << " ";
  33. // cerr << endl;
  34. }
  35. // puts("hahahahaha");
  36. // cerr << lb.top << endl;
  37. scanf("%d", &m);
  38. for (int i = 1; i <= m; i++) {
  39. scanf("%lld", &x);
  40. x -= have0;
  41. if (x > (1ll<<lb.top)) puts("-1");
  42. else {
  43. // cerr << "--" << x << " " << lb.top << endl;
  44. // cerr << lb.a[9] << endl;
  45. long long ans = 0;
  46. for (int j = 0; j <= 60; j++)
  47. if (x&(1ll<<j)) {
  48. ans ^= lb.a[lb.top-j];
  49. // cerr << lb.top-j << endl;
  50. }
  51. printf("%lld\n", ans);
  52. }
  53. }
  54. return 0;
  55. }

spfa多路增广 bzoj1458

行列建点,增广路对应方案。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 205;
  4. int n, m, k;
  5. int l[MAXN], c[MAXN];
  6. struct node {
  7. int to, next, flow, cost, neg;
  8. } edge[MAXN*MAXN*10];
  9. int head[MAXN], top = 0;
  10. inline void push(int i, int j, int f, int c)
  11. {
  12. ++top, edge[top] = (node) {j, head[i], f, c, top+1}, head[i] = top;
  13. ++top, edge[top] = (node) {i, head[j], 0, -c, top-1}, head[j] = top;
  14. }
  15. const int SS = MAXN-1, ST = MAXN-2, S = MAXN-3, T = MAXN-4;
  16. int cnt = 0;
  17. inline void push(int i, int j, int lb)
  18. {
  19. push(SS, j, lb, 0), push(i, ST, lb, 0);
  20. cnt += lb;
  21. }
  22. int dis[MAXN], vis[MAXN];
  23. deque<int> que;
  24. bool spfa()
  25. {
  26. memset(dis, 127/3, sizeof dis);
  27. memset(vis, 0, sizeof vis);
  28. vis[SS] = 1, dis[SS] = 0, que.push_back(SS);
  29. while (!que.empty()) {
  30. int nd = que.front(); que.pop_front(), vis[nd] = 0;
  31. for (int i = head[nd]; i; i = edge[i].next) {
  32. int to = edge[i].to, f = edge[i].flow, c = edge[i].cost;
  33. if (!f || dis[to] <= dis[nd]+c) continue;
  34. dis[to] = dis[nd]+c;
  35. if (!vis[to]) {
  36. vis[to] = 1;
  37. if (que.empty() || dis[to] > dis[que.front()]) que.push_back(to);
  38. else que.push_front(to);
  39. }
  40. }
  41. }
  42. return dis[ST] <= 23333333;
  43. }
  44. int dfs(int nd, int flow)
  45. {
  46. if (nd == ST || !flow) return flow;
  47. vis[nd] = 1;
  48. int ans = 0, t;
  49. for (int i = head[nd]; i; i = edge[i].next) {
  50. int to = edge[i].to, f = edge[i].flow, c = edge[i].cost;
  51. if (vis[to] || dis[to] != dis[nd]+c || !f) continue;
  52. t = dfs(to, min(flow, f));
  53. ans += t, flow -= t, edge[i].flow -= t, edge[edge[i].neg].flow += t;
  54. if (!flow) break;
  55. }
  56. return ans;
  57. }
  58. void mcf(int &c, int &f)
  59. {
  60. c = f = 0;
  61. int t;
  62. while (spfa()) {
  63. do {
  64. memset(vis, 0, sizeof vis);
  65. t = dfs(SS, INT_MAX);
  66. f += t, c += t*dis[ST];
  67. } while (t);
  68. }
  69. }
  70. bool g[101][101];
  71. int main()
  72. {
  73. scanf("%d%d%d", &n, &m, &k);
  74. for (int i = 1; i <= n; i++) scanf("%d", &l[i]);
  75. for (int i = 1; i <= m; i++) scanf("%d", &c[i]);
  76. for (int i = 1; i <= k; i++) {
  77. int u, v;
  78. scanf("%d%d", &u, &v);
  79. g[u][v] = true;
  80. }
  81. for (int i = 1; i <= n; i++) push(S, i, l[i]);
  82. for (int j = 1; j <= m; j++) push(n+j, T, c[j]);
  83. for (int i = 1; i <= n; i++)
  84. for (int j = 1; j <= m; j++)
  85. if (!g[i][j])
  86. push(i, n+j, 1, 1);
  87. push(T, S, INT_MAX, 0);
  88. int c, f;
  89. mcf(c, f);
  90. if (f != cnt) puts("JIONG!");
  91. else printf("%d\n", c);
  92. return 0;
  93. }

TODO LIST:

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