poj 1273.PIG (最大流)

深藏阁楼爱情的钟 2022-01-05 11:51 325阅读 0赞

网络流

关键是建图,思路在代码里

ContractedBlock.gif ExpandedBlockStart.gif

  1. /*
  2. 最大流SAP
  3. 邻接表
  4. 思路:基本源于FF方法,给每个顶点设定层次标号,和允许弧。
  5. 优化:
  6. 1、当前弧优化(重要)。
  7. 1、每找到以条增广路回退到断点(常数优化)。
  8. 2、层次出现断层,无法得到新流(重要)。
  9. 时间复杂度(m*n^2)
  10. */
  11. #include <iostream>
  12. #include <cstdio>
  13. #include <cstring>
  14. #define ms(a,b) memset(a,b,sizeof a)
  15. using namespace std;
  16. const int INF = 500;
  17. int G[INF][INF];
  18. struct node {
  19. int v, c, next;
  20. } edge[INF*INF*4];
  21. int pHead[INF*INF], SS, ST, nCnt;
  22. void addEdge (int u, int v, int c) {
  23. edge[++nCnt].v = v; edge[nCnt].c = c, edge[nCnt].next = pHead[u]; pHead[u] = nCnt;
  24. edge[++nCnt].v = u; edge[nCnt].c = 0, edge[nCnt].next = pHead[v]; pHead[v] = nCnt;
  25. }
  26. int SAP (int pStart, int pEnd, int N) {
  27. int numh[INF], h[INF], curEdge[INF], pre[INF];
  28. int cur_flow, flow_ans = 0, u, neck, i, tmp;
  29. ms (h, 0); ms (numh, 0); ms (pre, -1);
  30. for (i = 0; i <= N; i++) curEdge[i] = pHead[i];
  31. numh[0] = N;
  32. u = pStart;
  33. while (h[pStart] <= N) {
  34. if (u == pEnd) {
  35. cur_flow = 1e9;
  36. for (i = pStart; i != pEnd; i = edge[curEdge[i]].v)
  37. if (cur_flow > edge[curEdge[i]].c) neck = i, cur_flow = edge[curEdge[i]].c;
  38. for (i = pStart; i != pEnd; i = edge[curEdge[i]].v) {
  39. tmp = curEdge[i];
  40. edge[tmp].c -= cur_flow, edge[tmp ^ 1].c += cur_flow;
  41. }
  42. flow_ans += cur_flow;
  43. u = neck;
  44. }
  45. for ( i = curEdge[u]; i != 0; i = edge[i].next)
  46. if (edge[i].c && h[u] == h[edge[i].v] + 1) break;
  47. if (i != 0) {
  48. curEdge[u] = i, pre[edge[i].v] = u;
  49. u = edge[i].v;
  50. }
  51. else {
  52. if (0 == --numh[h[u]]) continue;
  53. curEdge[u] = pHead[u];
  54. for (tmp = N, i = pHead[u]; i != 0; i = edge[i].next)
  55. if (edge[i].c) tmp = min (tmp, h[edge[i].v]);
  56. h[u] = tmp + 1;
  57. ++numh[h[u]];
  58. if (u != pStart) u = pre[u];
  59. }
  60. }
  61. return flow_ans;
  62. }
  63. /*
  64. poj1149 最大流
  65. 建图:
  66. 每个顾客为一个节点,从源点到每个猪圈的第一个顾客连接一条容量为猪圈猪数目的边
  67. 从第一个顾客到同一个猪圈的其它顾客连一条容量无限的边
  68. 每个顾客到汇点的边的容量为他最大买的数量
  69. */
  70. int k, c, m, n,x,y,z;
  71. int vis[INF],sum[INF];
  72. void solve(){
  73. nCnt=1;
  74. for(int i=1;i<=ST;i++)
  75. for(int j=1;j<=ST;j++){
  76. if(G[i][j]) addEdge(i,j,G[i][j]);
  77. }
  78. int ans=SAP(SS,ST,ST);
  79. printf("%d\n",ans);
  80. }
  81. int main() {
  82. /*
  83. 先用邻接矩阵统计容量,再用前向星存边,表头在pHead[],初始化nCnt=1
  84. SS,ST分别为源点和汇点
  85. */
  86. scanf("%d %d",&m,&n);
  87. SS=n+1,ST=n+2;
  88. for(int i=1;i<=m;i++)
  89. scanf("%d",&sum[i]);
  90. for(int i=1;i<=n;i++){
  91. scanf("%d",&k);
  92. for(int j=1;j<=k;j++){
  93. scanf("%d",&x);
  94. if(!vis[x]){
  95. G[SS][i]+=sum[x];
  96. vis[x]=i;
  97. }
  98. else{
  99. G[vis[x]][i]=0xffff;
  100. }
  101. }
  102. scanf("%d",&k);
  103. G[i][ST]=k;
  104. }
  105. solve();
  106. return 0;
  107. }

转载于:https://www.cnblogs.com/keam37/p/3973519.html

发表评论

表情:
评论列表 (有 0 条评论,325人围观)

还没有评论,来说两句吧...

相关阅读

    相关 poj 2455 二分+

    这个因为点少用邻接矩阵做的。 题意:求由1到n的t条不重复路径中最大边权值的最小值。 思路:先对边权进行排序,然后二分边权值,建图求从1到n的最大流,当最大流为t时便求出答