当前位置:   article > 正文

hdu6214 Smallest Minimum Cut(网络流-最小割的最小边集)_网络流 minimum-cut

网络流 minimum-cut

题目

给定一张点数n(n<=200)和边数m(m<=1000)的图

求这张图最小割时,割掉的那些边的边数最少是多少

题解

其实自己之前这题做过,学最大权闭合子图的时候学过

然后这有个方法就是把边权放大,

比如w=10000w+1,然后再跑最小割,

原来相同最小割的边集再求最小割的时候,

会在边权放大之后有边数上的差别,

所以就是加的少的跑出来是新图的最小割,

也是我们想要的加的边少的最小割

然后把答案对10000取模,就是加的边数

除以10000向下取整,就是原来的最小割,

这个10000的下界是m+1,

不然边数带来的贡献会和一条边的权值搞混

心得

要总结只是因为Dinic板子被卡了,体验极差

感谢涛神提供的Dinic优化板子,其实只加了一行

队列的地方,如果怕动态开内存爆内存或爆时间,可以用数组模拟

从1995ms跑到170ms,强得一匹

代码

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<queue>
  5. #include<map>
  6. using namespace std;
  7. typedef long long ll;
  8. const ll INF=0x3f3f3f3f3f3f3f3fll;
  9. const int maxn=210;
  10. const int maxm=2e3+10;
  11. int level[maxn];
  12. int head[maxn],cnt;
  13. int t,n,m;
  14. int ss,ee;
  15. struct edge{int v,nex;ll w;}e[maxm];
  16. void init()
  17. {
  18. cnt=0;
  19. memset(head,-1,sizeof head);
  20. }
  21. void add(int u,int v,ll w)
  22. {
  23. e[cnt].v=v;
  24. e[cnt].w=w;
  25. e[cnt].nex=head[u];
  26. head[u]=cnt++;
  27. }
  28. bool bfs(int s,int t)
  29. {
  30. queue<int>q;
  31. memset(level,0,sizeof level);
  32. level[s]=1;
  33. q.push(s);
  34. while(!q.empty())
  35. {
  36. int x=q.front();
  37. q.pop();
  38. if(x==t)return 1;
  39. for(int u=head[x];~u;u=e[u].nex)
  40. {
  41. int v=e[u].v;ll w=e[u].w;
  42. if(!level[v]&&w)
  43. {
  44. level[v]=level[x]+1;
  45. q.push(v);
  46. }
  47. }
  48. }
  49. return 0;
  50. }
  51. ll dfs(int u,ll maxf,int t)
  52. {
  53. if(u==t)return maxf;
  54. ll ret=0;
  55. for(int i=head[u];~i;i=e[i].nex)
  56. {
  57. int v=e[i].v;ll w=e[i].w;
  58. if(level[u]+1==level[v]&&w)
  59. {
  60. ll MIN=min(maxf-ret,w);
  61. w=dfs(v,MIN,t);
  62. e[i].w-=w;
  63. e[i^1].w+=w;
  64. ret+=w;
  65. if(ret==maxf)break;
  66. }
  67. }
  68. if(!ret)level[u]=-1;//优化,防止重搜,说明u这一路不可能有流量了
  69. return ret;
  70. }
  71. ll Dinic(int s,int t)
  72. {
  73. ll ans=0;
  74. while(bfs(s,t))
  75. ans+=dfs(s,INF,t);
  76. return ans;
  77. }
  78. int main()
  79. {
  80. scanf("%d",&t);
  81. //n个点 m条边
  82. while(t--)
  83. {
  84. init();
  85. scanf("%d%d",&n,&m);
  86. scanf("%d%d",&ss,&ee);
  87. ss--,ee--;
  88. for(int j=0;j<m;++j)
  89. {
  90. int u,v;ll w;
  91. scanf("%d%d%lld",&u,&v,&w);
  92. u--,v--;
  93. w=w*10000+1;
  94. add(u,v,w);
  95. add(v,u,0);//有向图反向边权为0 无向图反向边权为w
  96. }
  97. ll ans=Dinic(ss,ee);
  98. printf("%lld\n",ans%10000);
  99. }
  100. return 0;
  101. }

 

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

闽ICP备14008679号