当前位置:   article > 正文

院科技文化节高级组 C.随时随地, 脉动回来(最小/最大费用流裸题)

院科技文化节高级组 C.随时随地, 脉动回来(最小/最大费用流裸题)

思路来源

舟亢学长

题解

裸最小费用最大流(最短路)

裸最大费用最大流(负权最短路再取反)

心得

本来比赛的时候有时间敲 预估自己30min

结果赛后补题敲了1h tm还WA了好几发

请学长debug结果是数组开小了GG

我怎么这么菜啊

还是对费用流理解不深啊

弧优化+SLF优化的SPFA是不可能被卡掉的啊

这样看来,手敲板子的学弟还真是遥不可及啊……

不禁让人怀念过目不忘的初中高中生涯……

如今已是按板子敲都能出各种bug的老年人了……

代码

  1. #include<bits/stdc++.h>
  2. typedef long long ll;
  3. using namespace std;
  4. const int maxn=110;//点的数量
  5. const int maxm=50005;//2*maxn*maxn+2*maxn 源点出maxn条 汇点入maxn条 中间点两两连
  6. const ll INF=1e18;
  7. struct edge
  8. {
  9. int u,v;
  10. ll cos,nex,w;
  11. }e[maxm];
  12. ll vis[2*maxn],dis[2*maxn];
  13. ll l[2*maxn],r[2*maxn],cost[2*maxn][2*maxn];
  14. ll tot;//总费用
  15. int head[maxn],cnt;
  16. int n,m;
  17. int s,t;
  18. void add(int u,int v,ll w,ll cos)
  19. {
  20. e[cnt].v=v;
  21. e[cnt].w=w;
  22. e[cnt].cos=cos;
  23. e[cnt].nex=head[u];
  24. head[u]=cnt++;
  25. }
  26. void add2(int u,int v,ll w,ll cos)
  27. {
  28. add(u,v,w,cos);
  29. add(v,u,0,-cos);
  30. }
  31. bool spfa()
  32. {
  33. for(int i=0;i<2*maxn;++i)
  34. dis[i]=INF;
  35. memset(vis,0,sizeof vis);
  36. vis[t]=1;
  37. dis[t]=0;
  38. deque<int>q;
  39. q.push_back(t);
  40. while(!q.empty())
  41. {
  42. int u=q.front();
  43. vis[u]=0;
  44. q.pop_front();
  45. for(int i=head[u];~i;i=e[i].nex)
  46. {
  47. int v=e[i].v;
  48. if(e[i^1].w>0&&dis[v]>dis[u]-e[i].cos)
  49. {
  50. dis[v]=dis[u]-e[i].cos;
  51. if(!vis[v])
  52. {
  53. vis[v]=1;
  54. if(!q.empty()&&dis[v]<dis[q.front()])
  55. q.push_front(v);
  56. else q.push_back(v);
  57. }
  58. }
  59. }
  60. }
  61. return dis[s]<INF;
  62. }
  63. ll dfs(int u,ll low,ll &tot)
  64. {
  65. vis[u]=1;
  66. if(u==t)return low;
  67. ll ans=0;
  68. for(int i=head[u];~i;i=e[i].nex)
  69. {
  70. int v=e[i].v;
  71. if(!vis[v]&&e[i].w&&dis[v]==dis[u]-e[i].cos)
  72. {
  73. ll now=dfs(v,min(low,e[i].w),tot);
  74. if(now>0)
  75. {
  76. tot+=e[i].cos*now;
  77. low-=now;
  78. ans+=now;
  79. e[i].w-=now;
  80. e[i^1].w+=now;
  81. if(low==0)break;
  82. }
  83. }
  84. }
  85. return ans;
  86. }
  87. ll max_flow(int s,int t,ll &tot)//tot返回费用 函数返回值为最大流
  88. {
  89. ll ans=0;
  90. while(spfa())
  91. {
  92. vis[t]=1;
  93. while(vis[t])
  94. {
  95. memset(vis,0,sizeof vis);
  96. ans+=dfs(s,INF,tot);
  97. }
  98. }
  99. return ans;
  100. }
  101. void init()
  102. {
  103. cnt=0;tot=0;
  104. for(int i=0;i<2*maxn;++i)
  105. dis[i]=INF;
  106. memset(head,-1,sizeof head);
  107. memset(vis,0,sizeof vis);
  108. }
  109. int main()
  110. {
  111. init();
  112. scanf("%d%d",&m,&n);
  113. //超级源 超级汇
  114. s=0;t=m+n+1;
  115. //左供货 右需求
  116. for(int i=1;i<=m;++i)
  117. {
  118. scanf("%lld",&l[i]);
  119. add2(s,i,l[i],0);//超级源点
  120. }
  121. for(int i=1;i<=n;++i)
  122. {
  123. scanf("%lld",&r[i]);
  124. add2(m+i,t,r[i],0);//超级汇点
  125. }
  126. for(int i=1;i<=m;++i)
  127. {
  128. for(int j=1;j<=n;++j)
  129. {
  130. scanf("%lld",&cost[i][j]);
  131. add2(i,m+j,l[i],cost[i][j]);//l[i]的流量 dis的费用
  132. }
  133. }
  134. max_flow(s,t,tot);
  135. printf("%lld\n",tot);
  136. init();
  137. for(int i=1;i<=m;++i)
  138. {
  139. add2(s,i,l[i],0);//超级源点
  140. }
  141. for(int i=1;i<=n;++i)
  142. {
  143. add2(m+i,t,r[i],0);//超级汇点
  144. }
  145. for(int i=1;i<=m;++i)
  146. {
  147. for(int j=1;j<=n;++j)
  148. {
  149. add2(i,m+j,l[i],-cost[i][j]);//l[i]的流量 dis的费用
  150. }
  151. }
  152. max_flow(s,t,tot);
  153. printf("%lld\n",-tot);
  154. return 0;
  155. }

 

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

闽ICP备14008679号