Description

小白在图论课上学到了一个新的概念——最小割,下课后小白在笔记本上写下了如下这段话: “对于一个图,某个对图中结点的划分将图中所有结点分成两个部分,如果结点s,t不在同一个部分中,则称这个划分是关于s,t的割。 对于带权图来说,将所有顶点处在不同部分的边的权值相加所得到的值定义为这个割的容量,而s,t的最小割指的是在关于s,t的割中容量最小的割” 现给定一张无向图,小白有若干个形如“图中有多少对点它们的最小割的容量不超过x呢”的疑问,小蓝虽然很想回答这些问题,但小蓝最近忙着挖木块,于是作为仍然是小蓝的好友,你又有任务了。

Input

输入文件第一行有且只有一个正整数T,表示测试数据的组数。 对于每组测试数据, 第一行包含两个整数n,m,表示图的点数和边数。 下面m行,每行3个正整数u,v,c(1<=u,v<=n,0<=c<=106),表示有一条权为c的无向边(u,v) 接下来一行,包含一个整数q,表示询问的个数 下面q行,每行一个整数x,其含义同题目描述。

Output

对于每组测试数据,输出应包括q行,第i行表示第i个问题的答案。对于点对(p,q)和(q,p),只统计一次(见样例)。

两组测试数据之间用空行隔开。

Sample Input

1
5 0
1
0

Sample Output

10

【数据范围】
对于100%的数据 T<=10,n<=150,m<=3000,q<=30,x在32位有符号整数类型范围内。
图中两个点之间可能有多条边

解题思路:
最小割树,用于解决全局任意点间的最小割。
考虑对于全局任意两个点的最小割将图分成的两部分,假如说我们在这两部分之间画一条分界线。
那么在两端各取一点再跑最小割,这时再画分界线,若两者最小割容量不同,那么那么这两条分界线一定没有交集。
贪心地想,若其中一个更优那么一定会取。
若第二条比第一条更优,那么一定说明第一遍时的两个点在第二条分界线同侧。
同时也说明,第二条分界线后除第二遍的终点以外,还会有点与这个点的最小割形成的割集与第二个割集相同。
所以可以每次取两个点跑最小割,划线。
然后下次在线同侧取点跑最小割划线,在线两端的点一定以这个割集为割集,所以更新答案即可。
分治的最坏时间复杂度为$O(n^2)$的,再套个Dinic时间复杂度为$O(n^4m)$的,不过这都是最坏的。
后者达上限非常困难前者也不容易。所以还是$O(玄学)$比较合适。
代码:
  1. #include<queue>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. const int oo=0x3f3f3f3f;
  6. struct pnt{
  7. int hd;
  8. int lyr;
  9. int now;
  10. bool vis;
  11. }p[];
  12. struct ent{
  13. int twd;
  14. int lst;
  15. int vls;
  16. int his;
  17. }e[];
  18. int cnt;
  19. int n,m;
  20. int s,t;
  21. int app[];
  22. int tmp[];
  23. int ans[][];
  24. std::queue<int>Q;
  25. void ade(int f,int t,int v)
  26. {
  27. cnt++;
  28. e[cnt].twd=t;
  29. e[cnt].vls=v;
  30. e[cnt].his=v;
  31. e[cnt].lst=p[f].hd;
  32. p[f].hd=cnt;
  33. return ;
  34. }
  35. bool Bfs(void)
  36. {
  37. while(!Q.empty())Q.pop();
  38. for(int i=;i<=n;i++)
  39. p[i].lyr=;
  40. p[s].lyr=;
  41. Q.push(s);
  42. while(!Q.empty())
  43. {
  44. int x=Q.front();
  45. Q.pop();
  46. for(int i=p[x].hd;i;i=e[i].lst)
  47. {
  48. int to=e[i].twd;
  49. if(p[to].lyr==&&e[i].vls>)
  50. {
  51. p[to].lyr=p[x].lyr+;
  52. if(to==t)
  53. return true;
  54. Q.push(to);
  55. }
  56. }
  57. }
  58. return false;
  59. }
  60. int Dfs(int x,int fll)
  61. {
  62. if(x==t)
  63. return fll;
  64. for(int& i=p[x].now;i;i=e[i].lst)
  65. {
  66. int to=e[i].twd;
  67. if(p[to].lyr==p[x].lyr+&&e[i].vls>)
  68. {
  69. int ans=Dfs(to,std::min(fll,e[i].vls));
  70. if(ans>)
  71. {
  72. e[i].vls-=ans;
  73. e[((i-)^)+].vls+=ans;
  74. return ans;
  75. }
  76. }
  77. }
  78. return ;
  79. }
  80. int Dinic()
  81. {
  82. int ans=;
  83. while(Bfs())
  84. {
  85. for(int i=;i<=n;i++)
  86. p[i].now=p[i].hd;
  87. int dlt;
  88. while(dlt=Dfs(s,oo))
  89. ans+=dlt;
  90. }
  91. return ans;
  92. }
  93. void dfs(int x)
  94. {
  95. if(p[x].vis)
  96. return ;
  97. p[x].vis=true;
  98. for(int i=p[x].hd;i;i=e[i].lst)
  99. {
  100. int to=e[i].twd;
  101. if(e[i].vls>)
  102. dfs(to);
  103. }
  104. return ;
  105. }
  106. void Build(int l,int r)
  107. {
  108. if(l==r)
  109. return ;
  110. s=app[l],t=app[r];
  111. for(int i=;i<=cnt;i+=)
  112. {
  113. e[i].vls=e[i].his;
  114. e[i+].vls=e[i+].his;
  115. e[i+].vls=e[i+].his;
  116. e[i+].vls=e[i+].his;
  117. }
  118. int tmf=Dinic();
  119. for(int i=;i<=n;i++)
  120. p[i].vis=false;
  121. dfs(s);
  122. for(int i=;i<=n;i++)
  123. if(p[i].vis)
  124. for(int j=;j<=n;j++)
  125. if(!p[j].vis)
  126. ans[i][j]=ans[j][i]=std::min(ans[i][j],tmf);
  127. int i=l-,j=r+;
  128. for(int k=l;k<=r;k++)
  129. if(p[app[k]].vis)
  130. tmp[++i]=app[k];
  131. else
  132. tmp[--j]=app[k];
  133. for(int k=l;k<=r;k++)
  134. app[k]=tmp[k];
  135. Build(l,i);
  136. Build(j,r);
  137. return ;
  138. }
  139. int main()
  140. {
  141. // freopen("a.in","r",stdin);
  142. int T;
  143. scanf("%d",&T);
  144. while(T--)
  145. {
  146. scanf("%d%d",&n,&m);
  147. cnt=;
  148. for(int i=;i<=n;i++)
  149. app[i]=i,
  150. p[i].hd=;
  151. memset(ans,0x3f,sizeof(ans));
  152. for(int i=;i<=m;i++)
  153. {
  154. int a,b,c;
  155. scanf("%d%d%d",&a,&b,&c);
  156. ade(a,b,c);
  157. ade(b,a,c);
  158. }
  159. Build(,n);
  160. int q;
  161. scanf("%d",&q);
  162. while(q--)
  163. {
  164. int x;
  165. scanf("%d",&x);
  166. int ansl=;
  167. for(int i=;i<n;i++)
  168. for(int j=i+;j<=n;j++)
  169. if(ans[i][j]<=x)
  170. ansl++;
  171. printf("%d\n",ansl);
  172. }
  173. puts("");
  174. }
  175. return ;
  176. }

2229: [Zjoi2011]最小割(最小割树)的更多相关文章

  1. bzoj2229: [Zjoi2011]最小割(分治最小割+最小割树思想)

    2229: [Zjoi2011]最小割 题目:传送门 题解: 一道非常好的题目啊!!! 蒟蒻的想法:暴力枚举点对跑最小割记录...绝对爆炸啊.... 开始怀疑是不是题目骗人...难道根本不用网络流?? ...

  2. 【BZOJ-2229】最小割 最小割树(最大流+分治)

    2229: [Zjoi2011]最小割 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 1565  Solved: 560[Submit][Status ...

  3. scu - 3254 - Rain and Fgj(最小点权割)

    题意:N个点.M条边(2 <= N <= 1000 , 0 <= M <= 10^5),每一个点有个权值W(0 <= W <= 10^5),现要去除一些点(不能去掉 ...

  4. 算法笔记--最大流和最小割 && 最小费用最大流 && 上下界网络流

    最大流: 给定指定的一个有向图,其中有两个特殊的点源S(Sources)和汇T(Sinks),每条边有指定的容量(Capacity),求满足条件的从S到T的最大流(MaxFlow). 最小割: 割是网 ...

  5. 3532: [Sdoi2014]Lis 最小字典序最小割

    3532: [Sdoi2014]Lis Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 865  Solved: 311[Submit][Status] ...

  6. HDU 1394 Minimum Inversion Number(最小逆序数 线段树)

    Minimum Inversion Number [题目链接]Minimum Inversion Number [题目类型]最小逆序数 线段树 &题意: 求一个数列经过n次变换得到的数列其中的 ...

  7. POJ 3659 Cell Phone Network / HUST 1036 Cell Phone Network(最小支配集,树型动态规划,贪心)-动态规划做法

    POJ 3659 Cell Phone Network / HUST 1036 Cell Phone Network(最小支配集,树型动态规划,贪心) Description Farmer John ...

  8. 紫书 例题 11-2 UVa 1395(最大边减最小边最小的生成树)

    思路:枚举所有可能的情况. 枚举最小边, 然后不断加边, 直到联通后, 这个时候有一个生成树.这个时候,在目前这个最小边的情况可以不往后枚举了, 可以直接更新答案后break. 因为题目求最大边减最小 ...

  9. BZOJ.2229.[ZJOI2011]最小割(最小割树)

    题目链接 题意:给定一张无向图,求任意两点之间的最小割. 在所有点中任选两个点作为源点\(S\).汇点\(T\),求它们之间的最小割\(ans\),并把原图分成两个点集\(S',T'\),用\(ans ...

随机推荐

  1. Linux VNC Viewer客户端

    1.realvnc-vnc-viewer 这个我感觉应该是做的做好用的VNC Viewer客户端了,毕竟是商业软件,但是VNC Viewer客户端是免费的.使用前 需要到官网下载对应发行版的软件包进行 ...

  2. Database Exception – yii\db\Exception

    在使用Yii2框架时遇到数据库无法访问的问题: 这个是由于 通常我们在参考 教程在 MAC OS LINUX下安装 MYSQL 时,默认将PHP.ini 中的以下三项留空导致的Yii2所需的PDO组建 ...

  3. 关于common.js里面的module.exports与es6的export default的思考总结

    背景 公司项目需要裁切功能,基于第三方图片裁切组件vue-cropper(0.4.0版本),封装了图片裁切组件(picture-cut)(放在公司内部组件库,仅限于公司内部使用) 在vue-cropp ...

  4. 使用jemdoc制作个人主页

    jemdoc官网说明: http://jemdoc.jaboc.net/index.html 作者的个人主页:https://jemnz.com/ 将下载的jemdoc.py文件和需要转化的xxx.j ...

  5. caioj 1073 动态规划入门(三维一边推:最长公共子序列加强版(三串LCS))

    三维的与二维大同小异,看代码. #include<cstdio> #include<cstring> #include<algorithm> #define REP ...

  6. Unity 如何将apk放到Android系统的system里

    有时我们需要用unity开发一款Android的系统软件,很坑,步骤如下: 1.用unity打包出来,签名. 2.用解压工具打开签过名的apk. 3.将lib里面的.so文件复制出来. 4.adb r ...

  7. ARM官方《CMSIS-RTOS教程》之线程Threads

    创建线程Creating Threads 一旦RTOS开始运行,就会有很多系统调用来管理和控制活跃的线程.默认情况下,main()函数自动被创建为第一个可运行的线程.在第一个例子里我们使用main() ...

  8. 【v2.x OGE教程 17】事务处理

    游戏代码中常常有些逻辑须要处理.因此OGE引擎加入了一个IUpdateHandler的类. IUpdateHandler类是OGE引擎中使用频率很之高的组件之中的一个,其本身是一个接口.内部有onUp ...

  9. BZOJ 3629 约数和定理+搜索

    呃呃 看到了这道题 没有任何思路-- 百度了一发题解 说要用约数和定理 就查了一发 http://baike.so.com/doc/7207502-7432191.html (不会的可以先学习一下) ...

  10. Android App中使用Gallery制作幻灯片播放效果

    http://www.jb51.net/article/83313.htm 我们有时候在iPhone手机上或者Windows上面看到动态的图片,可以通过鼠标或者手指触摸来移动它,产生动态的图片滚动效果 ...