题意: 有 n+1 个城市编号 0..n,有 m 条无向边,在 0 城市有个警察总部,最多可以派出 k 个逮捕队伍,在1..n 每个城市有一个犯罪团伙,
          每个逮捕队伍在每个城市可以选择抓或不抓,如果抓了 第 i  个城市的犯罪团伙,第 i-1 个城市的犯罪团伙就知道了消息  ,如果第 i-1 的犯罪

团伙之前没有被抓,任务就失败,问要抓到所有的犯罪团伙,派出的队伍需要走的最短路是多少。

分析: 最小费用最大流,需要注意的地方在于怎么去保证每个每个城市的团伙仅仅被抓一次,且在抓他之前,第i-1城市的团伙已经被抓。

方法是把拆点后的城市 i 和 i`之间的费用要设成一个很小的负值,这样可以保证该城市一定可以被访问到,

还有一点要注意的是派出的k个队可能有些队是不执行任务的,

方法是在 0 节点和 汇点之间连一条费用为0,容量为k的边

具体建图:

源点 s=2*n+1,

汇点 t=2*n+2,

每个城市拆成两个点 i 和 i+n,费用为 -100000,容量为 1

在源点和 0 之间连一条费用为 0 容量为 k 的边

在 0 和 城市 1..n之间连一条费用为 0 到 i 最短路容量为 1 的边(表示出发)

在 城市 n+1..n+n到汇点之间连一条费用为 0 到 i 最短路容量为 1 的边(表示回到总部)

在 城市 n+i..n+n 和 j(j>i)直间连一条费用为城市 i 到 j 最短路距离容量为 1 的边

求最小费用流。

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<cmath>
  6. #include<queue>
  7. #include<map>
  8. using namespace std;
  9. #define MOD 1000000007
  10. const int INF=0x3f3f3f3f;
  11. const double eps=1e-;
  12. typedef long long ll;
  13. #define cl(a) memset(a,0,sizeof(a))
  14. #define ts printf("*****\n");
  15. int n,m,tt;
  16. /*最小费用大流,求只需要取相反数结果即可。
  17. 点的总数为 N,点的编号 0~N -1*/
  18. const int MAXN = ;
  19. const int MAXM = ;
  20. struct Edge
  21. {
  22. int to,next,cap,flow,cost;
  23. }edge[MAXM];
  24. int head[MAXN],tol;
  25. int pre[MAXN],dis[MAXN];
  26. bool vis[MAXN];
  27. int N;//节点总个数,节点编号从0~N-1
  28. void init(int n)
  29. {
  30. N = n;
  31. tol = ;
  32. memset(head,-,sizeof(head));
  33. }
  34. void addedge(int u,int v,int cap,int cost)
  35. {
  36. edge[tol].to = v;
  37. edge[tol].cap = cap;
  38. edge[tol].cost = cost;
  39. edge[tol].flow = ;
  40. edge[tol].next = head[u];
  41. head[u] = tol++;
  42. edge[tol].to = u;
  43. edge[tol].cap = ;
  44. edge[tol].cost = -cost;
  45. edge[tol].flow = ;
  46. edge[tol].next = head[v];
  47. head[v] = tol++;
  48. }
  49. bool spfa(int s,int t)
  50. {
  51. queue<int>q;
  52. for(int i = ;i < N;i++)
  53. {
  54. dis[i] = INF;
  55. vis[i] = false;
  56. pre[i] = -;
  57. }
  58. dis[s] = ;
  59. vis[s] = true;
  60. q.push(s);
  61. while(!q.empty())
  62. {
  63. int u = q.front();
  64. q.pop();
  65. vis[u] = false;
  66. for(int i = head[u]; i != -;i = edge[i].next)
  67. {
  68. int v = edge[i].to;
  69. if(edge[i].cap > edge[i].flow &&
  70. dis[v] > dis[u] + edge[i].cost )
  71. {
  72. dis[v] = dis[u] + edge[i].cost;
  73. pre[v] = i;
  74. if(!vis[v])
  75. {
  76. vis[v] = true;
  77. q.push(v);
  78. }
  79. }
  80. }
  81. }
  82. if(pre[t] == -)return false;
  83. else return true;
  84. }
  85. //返回的是最大流,cost存的是最小费用
  86. int minCostMaxflow(int s,int t)
  87. {
  88. int flow = ;
  89. int cost = ;
  90. while(spfa(s,t))
  91. {
  92. int Min = INF;
  93. for(int i = pre[t];i != -;i = pre[edge[i^].to])
  94. {
  95. if(Min > edge[i].cap - edge[i].flow)
  96. Min = edge[i].cap - edge[i].flow;
  97. }
  98. for(int i = pre[t];i != -;i = pre[edge[i^].to])
  99. {
  100. edge[i].flow += Min;
  101. edge[i^].flow -= Min;
  102. cost += edge[i].cost * Min;
  103. }
  104. flow += Min;
  105. }
  106. return cost;
  107. }
  108. int c[MAXN][MAXN];
  109. void floyd(){
  110. for(int k=;k<=n;++k){
  111. for(int i=;i<=n;++i){
  112. for(int j=;j<=n;++j){
  113. c[i][j]=min(c[i][j],c[i][k]+c[k][j]);
  114. }
  115. }
  116. }
  117. }
  118. int main()
  119. {
  120. int i,j,k,ca=;
  121. #ifndef ONLINE_JUDGE
  122. freopen("1.in","r",stdin);
  123. #endif
  124. while(~scanf("%d%d%d",&n,&m,&k)&&n&&m&&k)
  125. {
  126. init(*n+);
  127. for(i=;i<=n;i++)
  128. for(j=;j<=n;j++)
  129. {
  130. c[i][j]=(i==j)?:INF;
  131. }
  132. int st=*n+;
  133. int ed=*n+;
  134. addedge(st,,k,);
  135. addedge(,ed,k,);
  136. while(m--)
  137. {
  138. int u,v,w;
  139. scanf("%d%d%d",&u,&v,&w);
  140. c[u][v]=c[v][u]=min(c[u][v],w);
  141. }
  142. floyd();
  143. for(i=;i<=n;i++)
  144. {
  145. addedge(,i,,c[][i]);
  146. addedge(i,i+n,,-);
  147. addedge(i+n,ed,,c[][i]);
  148. }
  149. for(i=;i<=n;i++)
  150. {
  151. for(j=i+;j<=n;j++)
  152. {
  153. addedge(i+n,j,,c[i][j]);
  154. }
  155. }
  156. printf("%d\n",minCostMaxflow(st,ed)+*n);
  157. }
  158. }

hdu 4411 2012杭州赛区网络赛 最小费用最大流 ***的更多相关文章

  1. hdu 4412 2012杭州赛区网络赛 期望

    虽然dp方程很好写,就是这个期望不知道怎么求,昨晚的BC也是 题目问题抽象之后为:在一个x坐标轴上有N个点,每个点上有一个概率值,可以修M个工作站, 求怎样安排这M个工作站的位置,使得这N个点都走到工 ...

  2. Our Journey of Dalian Ends 乌鲁木齐网络赛 最小费用最大流

    Life is a journey, and the road we travel has twists and turns, which sometimes lead us to unexpecte ...

  3. hdu 4273 2012长春赛区网络赛 三维凸包中心到最近面距离 ***

    新模板 /* HDU 4273 Rescue 给一个三维凸包,求重心到表面的最短距离 模板题:三维凸包+多边形重心+点面距离 */ #include<stdio.h> #include&l ...

  4. hdu 4741 2013杭州赛区网络赛 dfs ***

    起点忘记录了,一直wa 代码写的很整齐,看着很爽 #include<cstdio> #include<iostream> #include<algorithm> # ...

  5. hdu 4739 2013杭州赛区网络赛 寻找平行坐标轴的四边形 **

    是平行坐标轴的,排个序搞一下就行了,卧槽,水的不行 如果不是平行的,则需要按照边长来判断

  6. hdu 4738 2013杭州赛区网络赛 桥+重边+连通判断 ***

    题意:有n座岛和m条桥,每条桥上有w个兵守着,现在要派不少于守桥的士兵数的人去炸桥,只能炸一条桥,使得这n座岛不连通,求最少要派多少人去. 处理重边 边在遍历的时候,第一个返回的一定是之前去的边,所以 ...

  7. hdu 4293 2012成都赛区网络赛 dp ****

    题意:有n个人,可任意分成若干组,然后每个人个各提供一个信息,表示他们组前面有多少人,后面有多少人.问最多有多少个信息是不冲突的. 将n个人看成一组区间,然后每个人的信息可以表示为该人所在组的区间,然 ...

  8. hdu 4291 2012成都赛区网络赛 矩阵快速幂 ***

    分析:假设g(g(g(n)))=g(x),x可能非常大,但是由于mod 10^9+7,所以可以求出x的循环节 求出x的循环节后,假设g(g(g(n)))=g(x)=g(g(y)),即x=g(y),y也 ...

  9. hdu 4278 2012天津赛区网络赛 数学 *

    8进制转为10进制 #include<cstdio> #include<iostream> #include<algorithm> #include<cstr ...

随机推荐

  1. js里面的 InttoStr 和 StrtoInt

    javascript 字符串 和 数字的转换,话说好灵活,感觉回不去pascal了 int转换string: 1,var str=String(int); 2,num.toString(param) ...

  2. MyBatis <if>标签的一些问题

    1.常见错误: There is no getter for property named 'parentId' in 'class java.lang.Long'(或者String) org.myb ...

  3. VS2010调试速度很慢

    1.使用vs2010,感觉速度越来越慢.重新设置了vs2010的环境(在vs2010命令提示符下,执行devenv.exe /resetuserdata),居然解决了这个问题,速度跑的很好.网上有人说 ...

  4. Windows下配置Java开发环境

    学习Java第一步是配置本地开发环境,学习最基本的桌面开发,下面以win7为例配置Java开发环境,即:JDK+JRE+Eclipse,安装JDK的时候会默认安装JRE,根据提示安装就可以了. 首先去 ...

  5. XE 的程序升级 XE5 问题处理记录

    XE 的程序升级 XE5 问题处理记录 1.  [dcc32 Fatal Error] frxClass.pas(3556): F1026 File not found: 'xxxxx\Registr ...

  6. malloc原理和内存碎片

    当一个进程发生缺页中断的时候,进程会陷入内核态,执行以下操作: 1.检查要访问的虚拟地址是否合法 2.查找/分配一个物理页 3.填充物理页内容(读取磁盘,或者直接置0,或者啥也不干) 4.建立映射关系 ...

  7. 前台js分页,自己手写逻辑2

    //设置分页 var pageSize = 10; //设置一次显示多少页 var pageLimit = 5; $(function(){ $.post("rest/rtdbfix/lis ...

  8. Android Volley入门到精通:定制自己的Request

    经过前面两篇文章的学习,我们已经掌握了Volley各种Request的使用方法,包括StringRequest.JsonRequest.ImageRequest等.其中StringRequest用于请 ...

  9. 【leetcode】Binary Search Tree Iterator(middle)

    Implement an iterator over a binary search tree (BST). Your iterator will be initialized with the ro ...

  10. 【网络】VPN和代理服务器的区别

    来自:http://www.zhihujingxuan.com/19311.html [scotttony的回答(41票)]: VPN和ssh哪个比较好, 要看你怎么定义是“好”. ssh作为一个创建 ...