ID
Origin
Title
  34 / 81 Problem A POJ 3436 ACM Computer Factory
  92 / 195 Problem B POJ 3281 Dining
  55 / 148 Problem C POJ 1087 A Plug for UNIX
  59 / 111 Problem D POJ 2195 Going Home
  44 / 132 Problem E POJ 2516 Minimum Cost
  35 / 72 Problem F POJ 1459 Power Network
  40 / 217 Problem G HDU 4280 Island Transport
  42 / 133 Problem H HDU 4292 Food
  34 / 90 Problem I HDU 4289 Control
  28 / 90 Problem J UVA 10480 Sabotage
  19 / 37 Problem K HDU 2732 Leapin' Lizards
  13 / 136 Problem L HDU 3338 Kakuro Extension
  36 / 358 Problem M HDU 3605 Escape
  17 / 58 Problem N HDU 3081 Marriage Match II
  15 / 61 Problem O HDU 3416 Marriage Match IV
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

34 / 81 Problem A POJ 3436 ACM Computer Factory

没懂。。

此题是最大流问题。题目意思比较难懂。
看得比较纠结。
就是说有N台组装电脑的机器。电脑的组成部分共有P部分。
每台机器有P个输入输出规格。还有一个容量Q;

其中输入规格有三种情况:0,1,2

0:该部分不能存在

1:该部分必须保留

2:该部分可有可无

输出规格有2种情况:0,1

0:该部分不存在

1:该部分存在

要求的是生产电脑最大的台数,就是求网络中的最大流。

这相当于是生产线。需要自己去建图。

但是考虑到每台机器都有容量,所以把一台机器分成两个点,中间建一条容量的边。

同时如果一台机器的输出符合另一台机器的输入,则建一条容量无穷大的边。

同时要增加源点和汇点。输入没有1的连接源点,输出全部是1的连接汇点。

92 / 195 Problem B POJ 3281 Dining

本题能够想到用最大流做,那真的是太绝了。建模的方法很妙!
题意就是有N头牛,F个食物,D个饮料。
N头牛每头牛有一定的喜好,只喜欢几个食物和饮料。
每个食物和饮料只能给一头牛。一头牛只能得到一个食物和饮料。
而且一头牛必须同时获得一个食物和一个饮料才能满足。问至多有多少头牛可以获得满足。
最初相当的是二分匹配。但是明显不行,因为要分配两个东西,两个东西还要同时满足。
最大流建图是把食物和饮料放在两端。一头牛拆分成两个点,两点之间的容量为1.喜欢的食物和饮料跟牛建条边,容量为1.
加个源点和汇点。源点与食物、饮料和汇点的边容量都是1,表示每种食物和饮料只有一个。
这样话完全是最大流问题了,。

  1. /*
  2. POJ 3281 最大流
  3. //源点-->food-->牛(左)-->牛(右)-->drink-->汇点
  4. //精髓就在这里,牛拆点,确保一头牛就选一套food和drink的搭配
  5.  
  6. */
  7.  
  8. #include<stdio.h>
  9. #include<iostream>
  10. #include<string.h>
  11. #include<algorithm>
  12. #include<queue>
  13. using namespace std;
  14.  
  15. //****************************************************
  16. //最大流模板
  17. //初始化:g[][],start,end
  18. //******************************************************
  19. const int MAXN=;
  20. const int INF=0x3fffffff;
  21. int g[MAXN][MAXN];//存边的容量,没有边的初始化为0
  22. int path[MAXN],flow[MAXN],start,end;
  23. int n;//点的个数,编号0-n.n包括了源点和汇点。
  24.  
  25. queue<int>q;
  26. int bfs()
  27. {
  28. int i,t;
  29. while(!q.empty())q.pop();//把清空队列
  30. memset(path,-,sizeof(path));//每次搜索前都把路径初始化成-1
  31. path[start]=;
  32. flow[start]=INF;//源点可以有无穷的流流进
  33. q.push(start);
  34. while(!q.empty())
  35. {
  36. t=q.front();
  37. q.pop();
  38. if(t==end)break;
  39. //枚举所有的点,如果点的编号起始点有变化可以改这里
  40. for(i=;i<=n;i++)
  41. {
  42. if(i!=start&&path[i]==-&&g[t][i])
  43. {
  44. flow[i]=flow[t]<g[t][i]?flow[t]:g[t][i];
  45. q.push(i);
  46. path[i]=t;
  47. }
  48. }
  49. }
  50. if(path[end]==-)return -;//即找不到汇点上去了。找不到增广路径了
  51. return flow[end];
  52. }
  53. int Edmonds_Karp()
  54. {
  55. int max_flow=;
  56. int step,now,pre;
  57. while((step=bfs())!=-)
  58. {
  59. max_flow+=step;
  60. now=end;
  61. while(now!=start)
  62. {
  63. pre=path[now];
  64. g[pre][now]-=step;
  65. g[now][pre]+=step;
  66. now=pre;
  67. }
  68. }
  69. return max_flow;
  70. }
  71. int main()
  72. {
  73. int N,F,D;
  74. while(scanf("%d%d%d",&N,&F,&D)!=EOF)
  75. {
  76. memset(g,,sizeof(g));
  77. n=F+D+*N+;
  78. start=;
  79. end=n;
  80. for(int i=;i<=F;i++)g[][i]=;
  81. for(int i=F+*N+;i<=F+*N+D;i++)g[i][n]=;
  82. for(int i=;i<=N;i++)g[F+*i-][F+*i]=;
  83. int k1,k2;
  84. int u;
  85. for(int i=;i<=N;i++)
  86. {
  87. scanf("%d%d",&k1,&k2);
  88. while(k1--)
  89. {
  90. scanf("%d",&u);
  91. g[u][F+*i-]=;
  92. }
  93. while(k2--)
  94. {
  95. scanf("%d",&u);
  96. g[F+*i][F+*N+u]=;
  97. }
  98. }
  99. printf("%d\n",Edmonds_Karp());
  100. }
  101. return ;
  102. }

55 / 148 Problem C POJ 1087 A Plug for UNIX

题意:在一个房间里有N种插座和使用M种插座的电器,,这M种插座有些在现有的插座中不包含,不过可以通过适配器来转化,有K种类型的适配器来转化,让你求最少会有多少电器没法使用插座。

思路:最大二分匹配。即求出最多有多少电器有相应的插座,然后用M减去就是所求,不过建图有点难想,我也是看了别人的解题报告才明白的。将电器和相应的插座类型连接起来,将能相互转化的插座连接起来,然后将不能直接使用N种插座而通过适配器的转换就能用的电器和插座连起来,然后就是求M种电器和N种插座的最大匹配了。呃,其实看到很多博客都是用最大流做的,原本这题也是在最大流的练习中找到的,但是我发现最大匹配更好理解,而且二分匹配加上源点和汇点就能转化成最大流。

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <iostream>
  5. #include <algorithm>
  6. #include <map>
  7. #include <string>
  8. #define N 505
  9. using namespace std ;
  10.  
  11. map<string , int>p ;
  12. int mp[N][N] ;
  13. int n , m , k , nx ;
  14. int f[N] , d[N] ;
  15.  
  16. int dfs( int x )
  17. {
  18. int i ;
  19.  
  20. for ( i = m + ; i <= m + nx ; i++ )
  21. {
  22. if ( !f[i] && mp[x][i] )
  23. {
  24. f[i] = ;
  25. if ( !d[i] || dfs( d[i] ))
  26. {
  27. d[i] = x ;
  28. return ;
  29. }
  30. }
  31. }
  32. return ;
  33. }
  34. //二分匹配模板
  35. int floyd( )
  36. {
  37. int i , sum ;
  38. sum = ;
  39. memset( d , , sizeof ( d ));
  40. for ( i = ; i <= m ; i++ )
  41. {
  42. memset( f , , sizeof ( f ));
  43. if ( dfs( i ))
  44. sum++;
  45. }
  46. return sum ;
  47. }
  48.  
  49. int main()
  50. {
  51. int i , j , t ;
  52. string str1 , str2 ;
  53.  
  54. //freopen("input.txt" , "r" , stdin );
  55. //输入N种插座
  56. scanf ( "%d" , &n ) ;
  57. p.clear();
  58. nx = n ;
  59. for ( i = ; i <= n ; i++ )
  60. {
  61. cin>>str1 ;
  62. p[str1] = i ;
  63. }
  64.  
  65. //输入M种电器
  66. scanf ( "%d" , &m );
  67. for ( i = ; i <= m ; i++ )
  68. {
  69. cin>>str1>>str2 ;
  70. if ( p[str2] != )
  71. {
  72. int x = p[str2] ;
  73. mp[i][x+m] = ;
  74. }
  75. else
  76. {
  77. n++ ;
  78. p[str2] = n ;
  79. mp[i][n+m] = ;
  80. }
  81. }
  82.  
  83. //输入K种转化关系
  84. scanf ( "%d" , &k );
  85. for ( i = ; i <= k ; i++ )
  86. {
  87. cin>>str1>>str2 ;
  88. if ( p[str1] == )
  89. {
  90. n++ ;
  91. p[str1] = n ;
  92. }
  93. if ( p[str2] == )
  94. {
  95. n++ ;
  96. p[str2] = n ;
  97. }
  98. mp[p[str1]+m][p[str2]+m] = ;
  99. }
  100.  
  101. //将通过适配器可以使用原来N种插座的电器连起来。
  102. for ( i = ; i <= m + n ; i++ )
  103. for ( j = ; j <= m + n ; j++ )
  104. for ( t = ; t <= m + n ; t++ )
  105. if ( mp[j][i] && mp[i][t] && !mp[j][t] )
  106. mp[j][t] = ;
  107.  
  108. int flow = floyd( );
  109. printf ( "%d\n" , m - flow ) ;
  110. return ;
  111. }

最大流代码

  1. #include<stdio.h>
  2. #include<map>
  3. #include<iostream>
  4. #include<string.h>
  5. #include<string>
  6. #include<queue>
  7. using namespace std;
  8.  
  9. //****************************************************
  10. //最大流模板
  11. //初始化:g[][],start,end
  12. //******************************************************
  13. const int MAXN=;
  14. const int INF=0x3fffffff;
  15. int g[MAXN][MAXN];//存边的容量,没有边的初始化为0
  16. int path[MAXN],flow[MAXN],start,end;
  17. int n;//点的个数,编号0-n.n包括了源点和汇点。
  18.  
  19. queue<int>q;
  20. int bfs()
  21. {
  22. int i,t;
  23. while(!q.empty())q.pop();//把清空队列
  24. memset(path,-,sizeof(path));//每次搜索前都把路径初始化成-1
  25. path[start]=;
  26. flow[start]=INF;//源点可以有无穷的流流进
  27. q.push(start);
  28. while(!q.empty())
  29. {
  30. t=q.front();
  31. q.pop();
  32. if(t==end)break;
  33. //枚举所有的点,如果点的编号起始点有变化可以改这里
  34. for(i=;i<=n;i++)
  35. {
  36. if(i!=start&&path[i]==-&&g[t][i])
  37. {
  38. flow[i]=flow[t]<g[t][i]?flow[t]:g[t][i];
  39. q.push(i);
  40. path[i]=t;
  41. }
  42. }
  43. }
  44. if(path[end]==-)return -;//即找不到汇点上去了。找不到增广路径了
  45. return flow[end];
  46. }
  47. int Edmonds_Karp()
  48. {
  49. int max_flow=;
  50. int step,now,pre;
  51. while((step=bfs())!=-)
  52. {
  53. max_flow+=step;
  54. now=end;
  55. while(now!=start)
  56. {
  57. pre=path[now];
  58. g[pre][now]-=step;
  59. g[now][pre]+=step;
  60. now=pre;
  61. }
  62. }
  63. return max_flow;
  64. }
  65.  
  66. map<string,int>hash;
  67. int main()
  68. {
  69. // freopen("in.txt","r",stdin);
  70. // freopen("out.txt","w",stdout);
  71. string str1,str2;
  72. int N,M;
  73. int tol;
  74. while(scanf("%d",&N)!=EOF)
  75. {
  76. hash.clear();
  77. memset(g,,sizeof(g));
  78. start=;
  79. end=;
  80. tol=;
  81. while(N--)
  82. {
  83. cin>>str1;
  84. hash[str1]=tol;
  85. g[][tol]=;
  86. tol++;
  87. }
  88. scanf("%d",&M);
  89. for(int i=;i<M;i++)
  90. {
  91. cin>>str1>>str2;
  92. if(hash[str1]==)hash[str1]=tol++;
  93. if(hash[str2]==)hash[str2]=tol++;
  94. g[hash[str1]][end]=;
  95. g[hash[str2]][hash[str1]]=;
  96. }
  97. scanf("%d",&N);
  98. while(N--)
  99. {
  100. cin>>str1>>str2;
  101. if(hash[str1]==)hash[str1]=tol++;
  102. if(hash[str2]==)hash[str2]=tol++;
  103. g[hash[str2]][hash[str1]]=INF;
  104. }
  105. n=tol-;
  106. printf("%d\n",M-Edmonds_Karp());
  107.  
  108. }
  109. return ;
  110. }

59 / 111 Problem D POJ 2195 Going Home

hint.做过的题,解题报告见以前博客

44 / 132 Problem E POJ 2516 Minimum Cost

hint.做过的题,解题报告见以前博客

35 / 72 Problem F POJ 1459 Power Network

hint.做过的题,解题报告见以前博客

40 / 217 Problem G HDU 4280 Island Transport

题意:有N个岛屿之间有M双向条路,每条路每个小时最多能通过C个人,现在问一个小时内,最多能把多少个顾客从最西边的岛屿送至最东边的岛屿上。

思路:网络流,求最大流。建图:每条路连接的两个岛屿之间建立一条容量为C的双向边,取超级源点与汇点,源点与最西边的岛屿,汇点与最东边的岛屿建立一条流量为无穷大的边。

  1. /*
  2. 最大流模板
  3. sap
  4. */
  5. #include<stdio.h>
  6. #include<string.h>
  7. #include<algorithm>
  8. #include<iostream>
  9. using namespace std;
  10.  
  11. const int MAXN=;//点数的最大值
  12. const int MAXM=;//边数的最大值
  13. const int INF=0x3f3f3f3f;
  14.  
  15. struct Node
  16. {
  17. int from,to,next;
  18. int cap;
  19. }edge[MAXM];
  20. int tol;
  21. int head[MAXN];
  22. int dep[MAXN];
  23. int gap[MAXN];//gap[x]=y :说明残留网络中dep[i]==x的个数为y
  24.  
  25. int n;//n是总的点的个数,包括源点和汇点
  26.  
  27. void init()
  28. {
  29. tol=;
  30. memset(head,-,sizeof(head));
  31. }
  32.  
  33. void addedge(int u,int v,int w)
  34. {
  35. edge[tol].from=u;
  36. edge[tol].to=v;
  37. edge[tol].cap=w;
  38. edge[tol].next=head[u];
  39. head[u]=tol++;
  40. edge[tol].from=v;
  41. edge[tol].to=u;
  42. edge[tol].cap=;
  43. edge[tol].next=head[v];
  44. head[v]=tol++;
  45. }
  46. void BFS(int start,int end)
  47. {
  48. memset(dep,-,sizeof(dep));
  49. memset(gap,,sizeof(gap));
  50. gap[]=;
  51. int que[MAXN];
  52. int front,rear;
  53. front=rear=;
  54. dep[end]=;
  55. que[rear++]=end;
  56. while(front!=rear)
  57. {
  58. int u=que[front++];
  59. if(front==MAXN)front=;
  60. for(int i=head[u];i!=-;i=edge[i].next)
  61. {
  62. int v=edge[i].to;
  63. if(dep[v]!=-)continue;
  64. que[rear++]=v;
  65. if(rear==MAXN)rear=;
  66. dep[v]=dep[u]+;
  67. ++gap[dep[v]];
  68. }
  69. }
  70. }
  71. int SAP(int start,int end)
  72. {
  73. int res=;
  74. BFS(start,end);
  75. int cur[MAXN];
  76. int S[MAXN];
  77. int top=;
  78. memcpy(cur,head,sizeof(head));
  79. int u=start;
  80. int i;
  81. while(dep[start]<n)
  82. {
  83. if(u==end)
  84. {
  85. int temp=INF;
  86. int inser;
  87. for(i=;i<top;i++)
  88. if(temp>edge[S[i]].cap)
  89. {
  90. temp=edge[S[i]].cap;
  91. inser=i;
  92. }
  93. for(i=;i<top;i++)
  94. {
  95. edge[S[i]].cap-=temp;
  96. edge[S[i]^].cap+=temp;
  97. }
  98. res+=temp;
  99. top=inser;
  100. u=edge[S[top]].from;
  101. }
  102. if(u!=end&&gap[dep[u]-]==)//出现断层,无增广路
  103. break;
  104. for(i=cur[u];i!=-;i=edge[i].next)
  105. if(edge[i].cap!=&&dep[u]==dep[edge[i].to]+)
  106. break;
  107. if(i!=-)
  108. {
  109. cur[u]=i;
  110. S[top++]=i;
  111. u=edge[i].to;
  112. }
  113. else
  114. {
  115. int min=n;
  116. for(i=head[u];i!=-;i=edge[i].next)
  117. {
  118. if(edge[i].cap==)continue;
  119. if(min>dep[edge[i].to])
  120. {
  121. min=dep[edge[i].to];
  122. cur[u]=i;
  123. }
  124. }
  125. --gap[dep[u]];
  126. dep[u]=min+;
  127. ++gap[dep[u]];
  128. if(u!=start)u=edge[S[--top]].from;
  129. }
  130. }
  131. return res;
  132. }
  133.  
  134. int main()
  135. {
  136. // freopen("in.txt","r",stdin);
  137. // freopen("out.txt","w",stdout);
  138. int start,end;
  139. int m;
  140. int u,v,z;
  141. int T;
  142. scanf("%d",&T);
  143.  
  144. while(T--)
  145. {
  146. init();
  147. scanf("%d%d",&n,&m);
  148. int minx=;
  149. int maxx=-;
  150. int x,y;
  151. for(int i=;i<=n;i++)
  152. {
  153. scanf("%d%d",&x,&y);
  154. if(minx>x)
  155. {
  156. minx=x;
  157. start=i;
  158. }
  159. if(maxx<x)
  160. {
  161. maxx=x;
  162. end=i;
  163. }
  164. }
  165.  
  166. while(m--)
  167. {
  168. scanf("%d%d%d",&u,&v,&z);
  169. addedge(u,v,z);
  170. addedge(v,u,z);
  171. }
  172. //n一定是点的总数,这是使用SAP模板需要注意的
  173. int ans=SAP(start,end);
  174. printf("%d\n",ans);
  175. }
  176. return ;
  177. }

42 / 133 Problem H HDU 4292 Food

题意:有F种食物 D种饮料 它们都有一定的数量 有N个人 每个人都有自己喜欢吃的食物和饮料 (每个人至少要一种食物和饮料) 只有能满足他的要求时他才会接服务 求最大能满足多少人?
思路:网络流 建一超级源点 汇点 源点与食物相连 边权为其数量,汇点与饮料相连 边权也为其数量 把人分成两个点 之间的边权为1 每个人与之需要的食物和饮料相连 边权为1

  1. /*
  2. 题意:F种食物和D种饮料,每种食物和饮料的数目也是固定的,总共有N位顾客,每位顾客都只吃喝固定种类的食品
  3. 饮料,问最多能满足多少为顾客。
  4.  
  5. 题解:最大流+拆点;
  6. 建图:将每位顾客拆成两个点,同一顾客之间加入权值为1的有向边限制了只能是一位一位顾客来满足,再加入源点
  7. 来连接每一种食物,权值为该食物数量,然后根据顾客喜欢的食物连接顾客,权值为1,因为每位顾客只需1份食物饮
  8. 料,然后加入饮料结点并根据顾客喜好连接,权值同样为1,然后将饮料与汇点连接,权值为饮料的数目,最终求得
  9. 的最大流即为最多能满足的顾客。
  10. */
  11. #include <cstdio>
  12. #include <cstring>
  13.  
  14. #define EMAX 200000
  15. #define VMAX 1005
  16.  
  17. const int INF = 0xfffffff;
  18.  
  19. int head[VMAX],dis[VMAX],cur[VMAX],gap[VMAX],pre[VMAX];
  20. int EN;
  21. struct edge
  22. {
  23. int from,to;
  24. int weight;
  25. int next;
  26. }e[EMAX];
  27.  
  28. void insert(int u,int v,int w)
  29. {
  30. e[EN].to = v;
  31. e[EN].weight = w;
  32. e[EN].next = head[u];
  33. head[u] = EN++;
  34. e[EN].weight = ;
  35. e[EN].to = u;
  36. e[EN].next = head[v];
  37. head[v] = EN++;
  38. }
  39.  
  40. int sap(int s,int t, int n)
  41. {
  42. memset(dis,,sizeof(dis));
  43. memset(gap,,sizeof(gap));
  44. for(int i=; i<=n; i++)
  45. cur[i] = head[i];
  46. int u = pre[s];
  47. pre[s] = s;
  48. int ret = ;
  49. int temp = -;
  50. gap[] = n;
  51. bool flag;
  52. while(dis[s] < n)
  53. {
  54. flag = false;
  55. for(int &i = cur[u]; i != -; i = e[i].next)
  56. {
  57. int v = e[i].to;
  58. if(e[i].weight && dis[u] == dis[v] + )
  59. {
  60. if (temp == - || temp>e[i].weight)
  61. temp = e[i].weight;
  62. pre[v] = u;
  63. u = v;
  64. if(v == t)
  65. {
  66. ret += temp;
  67. for(u = pre[u];v != s;v = u,u = pre[u])
  68. {
  69. e[cur[u]].weight -= temp;
  70. e[cur[u]^].weight += temp;
  71. }
  72. temp = -;
  73. }
  74. flag = true;
  75. break;
  76. }
  77. }
  78. if (flag)
  79. continue;
  80.  
  81. int mindis = n;
  82. for(int i = head[u]; i != - ; i = e[i].next)
  83. {
  84. int v = e[i].to;
  85. if(e[i].weight && mindis > dis[v])
  86. {
  87. cur[u] = i;
  88. mindis = dis[v];
  89. }
  90. }
  91. gap[dis[u]]--;
  92. if( gap[dis[u]] == )
  93. break;
  94. dis[u] = mindis+;
  95. gap[dis[u]]++;
  96. u = pre[u];
  97. }
  98. return ret;
  99. }
  100.  
  101. int main(void)
  102. {
  103. int n,f,d,t;
  104. char s[];
  105. while (scanf("%d%d%d",&n,&f,&d) == )
  106. {
  107. memset(head,-,sizeof(head));
  108. EN = ;
  109. for(int i=; i<=f; i++)
  110. {
  111. scanf("%d",&t);
  112. insert(,i,t);//源点加边
  113. }
  114. for(int i=; i<=d; i++)
  115. {
  116. scanf("%d",&t);
  117. insert(f+*n+i,f+*n+d+,t);//汇点加边
  118. }
  119. for(int i=; i<=n; i++)
  120. insert(f+i,f+n+i,);//拆点
  121. for(int i=; i<=n; i++)
  122. {
  123. scanf("%s",s+);
  124. for(int j=; j<=f; j++)
  125. if (s[j] == 'Y')
  126. insert(j,f+i,);//顾客与食物加边
  127. }
  128. for(int i=; i<=n; i++)
  129. {
  130. scanf("%s",s+);
  131. for(int j=; j<=d; j++)
  132. if (s[j] == 'Y')
  133. insert(f+n+i,f+*n+j,);//顾客与饮料加边
  134. }
  135. printf("%d\n",sap(,f+*n+d+,f+*n+d+));
  136. }
  137. return ;
  138. }

34 / 90 Problem I HDU 4289 Control

成都赛区网络赛1002题。
一场网络赛两题最大流,用SAP模板可以秒掉。
  1. //
  2. /*
  3. HDU 4289
  4. G++ 62ms 1888K
  5. 最大流
  6. SAP
  7. */
  8. #include<stdio.h>
  9. #include<iostream>
  10. #include<map>
  11. #include<set>
  12. #include<algorithm>
  13. #include<string.h>
  14. #include<stdlib.h>
  15. using namespace std;
  16.  
  17. const int MAXN=;//点数的最大值
  18. const int MAXM=;//边数的最大值
  19. const int INF=0x3f3f3f3f;
  20.  
  21. struct Node
  22. {
  23. int from,to,next;
  24. int cap;
  25. }edge[MAXM];
  26. int tol;
  27. int head[MAXN];
  28. int dep[MAXN];
  29. int gap[MAXN];//gap[x]=y:说明残留网络中 dep[i]==x的个数为y
  30.  
  31. int n;//点的实际个数,一定是总的点的个数,包括源点和汇点
  32. void init()
  33. {
  34. tol=;
  35. memset(head,-,sizeof(head));
  36. }
  37. void addedge(int u,int v,int w)
  38. {
  39. edge[tol].from=u;
  40. edge[tol].to=v;
  41. edge[tol].cap=w;
  42. edge[tol].next=head[u];
  43. head[u]=tol++;
  44. edge[tol].from=v;
  45. edge[tol].to=u;
  46. edge[tol].cap=;
  47. edge[tol].next=head[v];
  48. head[v]=tol++;
  49. }
  50. void BFS(int start,int end)
  51. {
  52. memset(dep,-,sizeof(dep));
  53. memset(gap,,sizeof(gap));
  54. gap[]=;
  55. int que[MAXN];
  56. int front,rear;
  57. front=rear=;
  58. dep[end]=;
  59. que[rear++]=end;
  60. while(front!=rear)
  61. {
  62. int u=que[front++];
  63. if(front==MAXN)front=;
  64. for(int i=head[u];i!=-;i=edge[i].next)
  65. {
  66. int v=edge[i].to;
  67. if(edge[i].cap!=||dep[v]!=-)continue;
  68. que[rear++]=v;
  69. if(rear==MAXN)rear=;
  70. dep[v]=dep[u]+;
  71. ++gap[dep[v]];
  72. }
  73. }
  74. }
  75. int SAP(int start,int end)
  76. {
  77. int res=;
  78. BFS(start,end);
  79. int cur[MAXN];
  80. int S[MAXN];
  81. int top=;
  82. memcpy(cur,head,sizeof(head));
  83. int u=start;
  84. int i;
  85. while(dep[start]<n)
  86. {
  87. if(u==end)
  88. {
  89. int temp=INF;
  90. int inser;
  91. for(i=;i<top;i++)
  92. if(temp>edge[S[i]].cap)
  93. {
  94. temp=edge[S[i]].cap;
  95. inser=i;
  96. }
  97. for(i=;i<top;i++)
  98. {
  99. edge[S[i]].cap-=temp;
  100. edge[S[i]^].cap+=temp;
  101. }
  102. res+=temp;
  103. top=inser;
  104. u=edge[S[top]].from;
  105. }
  106. if(u!=end&&gap[dep[u]-]==)//出现断层,无增广路
  107. break;
  108. for(i=cur[u];i!=-;i=edge[i].next)
  109. if(edge[i].cap!=&&dep[u]==dep[edge[i].to]+)
  110. break;
  111. if(i!=-)
  112. {
  113. cur[u]=i;
  114. S[top++]=i;
  115. u=edge[i].to;
  116. }
  117. else
  118. {
  119. int min=n;
  120. for(i=head[u];i!=-;i=edge[i].next)
  121. {
  122. if(edge[i].cap==)continue;
  123. if(min>dep[edge[i].to])
  124. {
  125. min=dep[edge[i].to];
  126. cur[u]=i;
  127. }
  128. }
  129. --gap[dep[u]];
  130. dep[u]=min+;
  131. ++gap[dep[u]];
  132. if(u!=start)
  133. u=edge[S[--top]].from;
  134. }
  135.  
  136. }
  137. return res;
  138. }
  139.  
  140. int main()
  141. {
  142. //freopen("B.in","r",stdin);
  143. //freopen("B.out","w",stdout);
  144. int N,M;
  145. int u,v;
  146. int start;
  147. int end;
  148. while(scanf("%d%d",&N,&M)!=EOF)
  149. {
  150. init();
  151. scanf("%d%d",&start,&end);
  152. start=*start-;
  153. end=*end;
  154. n=*N;
  155. for(int i=;i<=N;i++)
  156. {
  157. scanf("%d",&u);
  158. addedge(*i-,*i,u);
  159. addedge(*i,*i-,u);
  160. }
  161. while(M--)
  162. {
  163. scanf("%d%d",&u,&v);
  164. addedge(*u,*v-,INF);
  165. addedge(*v,*u-,INF);//这里一定要注意
  166. }
  167. printf("%d\n",SAP(start,end));
  168. }
  169. return ;
  170. }

28 / 90 Problem J UVA 10480 Sabotage

最大流

19 / 37 Problem K HDU 2732 Leapin' Lizards

最大流

13 / 136 Problem L HDU 3338 Kakuro Extension

很神奇的最大流的题目。很有意思。

题目意思就是在n*m的格子中,有黑白两种格子。要在白格子中填入数字1~9
* 每一段横竖连续的白格子的和是知道的。
* 求出一种满足的,保证有解。
* 最大流。
* 按照横竖段进行编号。然后行进列出,构造图形。
*
* 为了保证填入的数字是1~9,所以一开始每个格子减掉了1,相应的流入和流出都减掉。
* 然后格子的边的赋值为8.
* 还有就是要记录下相应边的编号,便于输出结果。

36 / 358 Problem M HDU 3605 Escape

这题一看题目是很简单的最大流。
但是数据好大,试了很多模板,都是TLE。
后来发现可以合并点,
因为m<=10.
所以用二进制记录。
在n个点中,如果是一样的就合并。
这样最多是1024+m+2个点。
 
但是这题还是很坑。。。。在HDU上用G++交无论如何都是TLE的。直接读入数据输出都是TLE.
改成C++就AC了。。。
 

17 / 58 Problem N HDU 3081 Marriage Match II

最大流+二分+并查集

15 / 61 Problem O HDU 3416 Marriage Match IV

这题就是求从A到B的最短路径的条数。

一条边只能经过一次。

先通过最短路去除掉没有用的边。

然后用一次最大流就是答案了。

从A和B分别出发求最短路dist1,dist2.

注意从B求得额时候要反向。

如果dist1[a]+dist2[b]+c==dist1[B].那么这条边就是有用的。。

我用的SPFA求最短路的。

[kuangbin带你飞]专题十一 网络流的更多相关文章

  1. Kuangbin 带你飞专题十一 网络流题解 及模版 及上下界网络流等问题

    首先是几份模版 最大流:虽然EK很慢但是优势就是短.求最小割的时候可以根据增广时的a数组来判断哪些边是割边.然而SAP的最大流版我只会套版,并不知道该如何找到这个割边.在尝试的时候发现了一些问题.所以 ...

  2. [kuangbin带你飞]专题十一 网络流个人题解(L题留坑)

    A - ACM Computer Factory 题目描述:某个工厂可以利用P个部件做一台电脑,有N个加工用的机器,但是每一个机器需要特定的部分才能加工,给你P与N,然后是N行描述机器的最大同时加工数 ...

  3. [kuangbin带你飞]专题1-23题目清单总结

    [kuangbin带你飞]专题1-23 专题一 简单搜索 POJ 1321 棋盘问题POJ 2251 Dungeon MasterPOJ 3278 Catch That CowPOJ 3279 Fli ...

  4. 【算法系列学习三】[kuangbin带你飞]专题二 搜索进阶 之 A-Eight 反向bfs打表和康拓展开

    [kuangbin带你飞]专题二 搜索进阶 之 A-Eight 这是一道经典的八数码问题.首先,简单介绍一下八数码问题: 八数码问题也称为九宫问题.在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的 ...

  5. [kuangbin带你飞]专题十 匹配问题

        A-L 二分匹配 M-O 二分图多重匹配 P-Q 二分图最大权匹配 R-S 一般图匹配带花树 模板请自己找     ID Origin Title   61 / 72 Problem A HD ...

  6. [kuangbin带你飞]专题十 匹配问题 一般图匹配

    过去做的都是二分图匹配 即 同一个集合里的点 互相不联通 但是如果延伸到一般图上去 求一个一般图的最大匹配 就要用带花树来解决 带花树模板 用来处理一个无向图上的最大匹配 看了一会还是不懂  抄了一遍 ...

  7. [kuangbin带你飞]专题十 匹配问题 二分匹配部分

    刚回到家 开了二分匹配专题 手握xyl模板 奋力写写写 终于写完了一群模板题 A hdu1045 对这个图进行 行列的重写 给每个位置赋予新的行列 使不能相互打到的位置 拥有不同的行与列 然后左行右列 ...

  8. [kuangbin带你飞]专题六 最小生成树

    学习最小生成树已经有一段时间了 做一些比较简单的题还算得心应手..花了三天的时间做完了kuangbin的专题 写一个题解出来记录一下(虽然几乎都是模板题) 做完的感想:有很多地方都要注意 n == 1 ...

  9. [kuangbin带你飞]专题十五 数位DP

            ID Origin Title   62 / 175 Problem A CodeForces 55D Beautiful numbers   30 / 84 Problem B HD ...

随机推荐

  1. 深入认识JavaScript 中的this指针

    深入认识JavaScript 中的this指针this指针是面向对象程序设计中的一项重要概念,它表示当前运行的对象.在实现对象的方法时,可以使用this指针来获得该对象自身的引用.和传统意义的面向对象 ...

  2. 用Navicat连接Oracle数据库时报错ORA-28547:connection to server failed,probable Oracle Net admin error

    用Navicat连接Oracle数据库时出现如下错误 上网一查原来是oci.dll版本不对.因为Navicat是通过Oracle客户端连接Oracle服务器的,Oracle的客户端分为两种,一种是标准 ...

  3. Android 隐藏Fragment

    1.隐藏Fragment FragmentManager fManager = getFragmentManager(); fManager.beginTransaction() .setCustom ...

  4. [转]StringUtils方法

    摘自http://blog.sina.com.cn/s/blog_4550f3ca0100qrsd.html org.apache.commons.lang.StringUtils中方法的操作对象是j ...

  5. Math.Round函數

    Math.Round這個函數的解釋是將值按指定的小數位數舍入,但並不就是四捨五入.這種舍入有時稱為就近舍入或四舍六入五成雙 其實在 VB, VBScript, C#, J#, T-SQL 中 Roun ...

  6. erlang远程加载模块须知

    erlang加载本地beam到远程节点,需要把依赖库一个个手动加载,否则他不会自动加载. 另外,创建lib的话,使用 rebar-creator create-lib

  7. Return 和 Break 的区别

    前段日子发布的负面情绪太多了,哦哦,其实我需要的是努力,努力提高自己的真实能力.经历了好多的鄙视否定,我已经没有最初那么敏感,心态平和了许多.我没有借口说基础不好了,一年了,要努力的话,那么我应该不会 ...

  8. u-boot启动流程分析(1)_平台相关部分

    转自:http://www.wowotech.net/u-boot/boot_flow_1.html 1. 前言 本文将结合u-boot的“board—>machine—>arch—> ...

  9. [cmd]linux 常用命令

    1. 磁盘/文件大小中占用情况 df -h: 磁盘大小占用情况 du -h file: 文件夹大小,du -ah file文件夹内所有文件占用情况 du -sh dir: 可以查看文件夹大小,而不列出 ...

  10. Sublime Text 介绍、用法、插件等

    个人常用插件: AlignmentBracket Highlighter 此插件能完成括号高亮匹对DocBlockrEmmentNodejsPackage ControlPrefixr   CSS3中 ...