当前位置:   article > 正文

Codeforces Round 911 (Div. 2) E题

Codeforces Round 911 (Div. 2) E题

主要由三部分组成:Tarjan算法,拓扑排序(topsort),以及动态规划(dp)。

  1. Tarjan算法:这是一种用于在图中查找强连通分量或割点的算法。在这段代码中,Tarjan算法被用于找出图中的强连通分量。每个强连通分量被视为一个节点,节点的权值为该强连通分量中所有节点的权值之和。

  2. 拓扑排序:拓扑排序是对有向无环图(DAG)进行排序的算法,它会按照依赖关系进行排序。在这段代码中,拓扑排序被用于确定强连通分量(视为节点)之间的依赖关系,从而确定最优的遍历顺序。

  3. 动态规划动态规划是一种通过把原问题分解为相互重叠的子问题来求解问题的方法。在这段代码中,动态规划被用于在给定的依赖关系下,找出权值最大的路径

对于一个路径来说,如果走入了一个强连通分量,无论如何都要走完这个强连通分量的点

缩点之后就对有向无环图(DAG)进行拓扑排序 + dp

代码的状态转移方程可以表示为:

  • 对于每个节点v,我们遍历其所有前驱节点u

  • 如果f[u] > f[v],那么我们更新f[v] = f[u],并且g[v] = g[u]。这表示如果从根节点到节点u的路径上能集聚的点数多于从根节点到节点v的路径,那么我们就选择从根节点到节点u的路径,并且更新从根节点到节点v的路径的最小权值为从根节点到节点u的路径的最小权值。

  • 如果f[u] == f[v],那么我们更新g[v] = min(g[u], g[v])。这表示如果从根节点到节点u的路径上能集聚的点数等于从根节点到节点v的路径,那么我们就选择这两条路径中权值最小的那条。

所以,状态转移方程可以表示为:

  • f[v] = max(f[u]),其中uv的所有前驱节点。
  • g[v] = min(g[u]),其中u是使得f[u] = f[v]的所有节点。

以下是代码

  1. #include <iostream>
  2. #include <cstring>
  3. #include <stack>
  4. #include <algorithm>
  5. #include <queue>
  6. #include <vector>
  7. #include <cmath>
  8. #include <set>
  9. #define mem(a,b) memset(a,b,sizeof(a))
  10. #define rep(a, b, c) for (a = b; a <= c; a++)
  11. #define int long long
  12. using namespace std;
  13. typedef double db;
  14. typedef pair<int,int> pii;
  15. const int N = 200010, M = 200010 * 2;
  16. const int inf = 3e18;
  17. int n,m;
  18. int h[N],H[N],ne[M],e[M],idx; // 领链表
  19. int w[N];
  20. int dfn[N],low[N],id[N],timestamp,scc_cnt;
  21. stack <int> stk;
  22. bool isStk[N];
  23. int sz[N],din[N],val[N];
  24. void add(int h[],int a,int b){
  25. e[idx] = b;
  26. ne[idx] = h[a];
  27. h[a] = idx ++;
  28. }
  29. void tarjan(int u){
  30. dfn[u] = low[u] = ++ timestamp;
  31. stk.push(u); isStk[u] = true;
  32. for (int i = h[u] ; ~i ; i = ne[i]){
  33. int x = e[i];
  34. // 后向边
  35. if (!dfn[x]){
  36. tarjan(x);
  37. low[u] = min(low[u],low[x]);
  38. }
  39. // 前向边
  40. else if (isStk[x]){
  41. low[u] = min(low[u],dfn[x]);
  42. }
  43. }
  44. // 如果该点是连通分量的顶点
  45. if (dfn[u] == low[u]){
  46. int y;
  47. scc_cnt ++;
  48. do {
  49. y = stk.top(); stk.pop();
  50. isStk[y] = false;
  51. id[y] = scc_cnt;
  52. sz[scc_cnt] ++ ;
  53. val[scc_cnt] += w[y];
  54. } while (y != u);
  55. }
  56. }
  57. int f[N]; // f[i] 从根到i这个点所能集聚的最多的点
  58. int g[N]; // g[i] f[i]max的前提现 最小的g[i]
  59. void topsort(int h[]){
  60. queue <int> q;
  61. int i;
  62. rep(i,1,scc_cnt){
  63. if (!din[i]){
  64. q.push(i);
  65. g[i] = 0;
  66. }
  67. }
  68. while (q.size()){
  69. int u = q.front(); q.pop();
  70. f[u] += sz[u];
  71. g[u] += val[u];
  72. for (i = h[u]; ~i; i = ne[i]){
  73. int v = e[i];
  74. if (f[u] > f[v]){
  75. f[v] = f[u];
  76. g[v] = g[u];
  77. }else if (f[u] == f[v]){
  78. g[v] = min(g[u],g[v]);
  79. }
  80. din[v] --;
  81. if (din[v] == 0) q.push(v);
  82. }
  83. }
  84. int ans_long = 0, ans_val = inf;
  85. rep(i,1,scc_cnt){
  86. if (ans_long < f[i]){
  87. ans_long = f[i];
  88. ans_val = g[i];
  89. }else if(ans_long == f[i]){
  90. ans_val = min(ans_val,g[i]);
  91. }
  92. }
  93. cout << ans_long << ' ' << ans_val << endl;
  94. }
  95. void solve(){
  96. int i;
  97. {
  98. cin >> n >> m;
  99. timestamp = scc_cnt = idx = 0;
  100. while (stk.size()) stk.pop();
  101. int i;
  102. rep(i,1,n){
  103. cin >> w[i];
  104. // init
  105. H[i] = h[i] = -1;
  106. dfn[i] = low[i] = id[i] = 0;
  107. isStk[i] = 0;
  108. din[i] = val[i] = sz[i] = 0;
  109. f[i] = 0;
  110. g[i] = inf;
  111. }
  112. while (m --){
  113. int a,b;
  114. cin >> a >> b;
  115. add(h,a,b);
  116. }
  117. rep(i,1,n){
  118. if (!dfn[i]){
  119. tarjan(i);
  120. }
  121. }
  122. }
  123. // 去重用的
  124. set <int> edge;
  125. int u;
  126. rep(u,1,n){
  127. for (int i = h[u]; ~i; i = ne[i]){
  128. int v = e[i];
  129. int A = id[u], B = id[v];
  130. if (A != B && !edge.count(A * N + B)){
  131. edge.insert(A * N + B);
  132. add(H,A,B);
  133. din[B] ++;
  134. }
  135. }
  136. }
  137. topsort(H);
  138. }
  139. signed main(){
  140. cin.tie(0);
  141. int Gold_age = 1;
  142. cin >> Gold_age;
  143. while (Gold_age --){
  144. solve();
  145. }
  146. system("pause");
  147. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/55205
推荐阅读
相关标签
  

闽ICP备14008679号