- 1、本文档共6页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
美国中学奶牛通信
美国中学生竞赛——奶牛通信解题思路:本题要求出最少损坏多少个计算机,才能使计算机 a 和 b 之间不能通讯。它的数学模型就是在一个图中最少去掉多少个点,才能使指定的两个点不能连通。它实际上等于这两点之间互不相交的路的最多数目。对于此类问题,在图论中称作求最小割集问题,它可以用求最大流的方法来解决。在求最大流之前,先将原图作一些变换:将图中除了 a、 b 两点外的点 i 都拆成两个点i和点 n + i( n 为图中点的数目) ,这两点之间连一条容量为 1 的有向边 i→n + i ;对于原图中的任意一条无向边( i , j ) ,在新图中变为有向边 n + i→j 和 n + j→i ,这些边的容量为∞求最大流思路:核心——退流的概念---后向弧仔细分析图2.1,我们发现,流量是可以增加的:图3.1把一个流量弧(B,C)和(C,T)上的流退回到B点,改道从B-D-E-T走,就可以增加流量了,如下图:图3.2图3.1不能“直接寻找增大流的路径”,是因为当初有些弧上的流选择不“恰当”,要“退流”。加入退流思想---后向弧,就能再次“直接寻找增大流的路径”。增广路径(可改进路径)的定义若P是网络中连结源点s和汇点t的一条路,我们定义路的方向是从s到t,则路上的弧有两种:前向弧---弧的方向与路的方向一致。前向弧的全体记为P+;后向弧---弧的方向与路的方向相反。后向弧的全体记为P-;设F是一个可行流,P 是从s到t的一条路,若P满足下列条件:在P+的所有前向弧(u,v)上,0≦f(u,v) C(u,v);在P-的所有后向弧(u,v)上,0f(u,v) ≦C(u,v);则称P是关于可行流F的一条可增广路径。图3.3本图中:S-A-C-B-D-E-T 为一增广路径。其中(C,B)为后向弧,其它为前向弧。在增广路径上的改进算法:求路径可改进量;修改增广路径上的流量;由于要考虑前向弧、后向弧,分析、描述时不简洁,在图2.1上直观看也不容易看出增广路径。因此我们把已经有的流量从容量中分离出来表示,引入一个与原问题等价的附加网络1:残留网络。图4.1 其中,前向弧(黑色)上的容量为“剩余容量”=C(u,v)-f(u,v);后向弧(红色)上的容量为“可退流量”=f(v,u)。最大流定理:如果残留网络找不到增广路径,则当前流为最大流;反之当前流不为最大流,则一定有增广路径。根据这个定理,得出计算最大流的基本流程有上述流程图可以看出,计算最大流的关键在于怎样找可增广路径。常用方法有:1:深度优先搜索DFS。2:宽度优先搜索BFS。3:标号搜索PFS——即类似Dijkstra算法的标号法。通过求最大流计算最小割切定理:在一个给定的网络图上,流的极大值等于割切容量的最小值,即Max{F}=min{C(S,S1)}源代码:输入举例:3 2 1 21 32 38 14 1 21 31 61 71 82 32 42 52 62 73 64 54 74 87 80 0 0 0输出举例:Network # 113Network # 243 4 6 7(3 6 7 8 也对)#includeiostream#includealgorithm#includestring#includecstdio#includestring#includecstring#includecmathusing namespace std;const int maxn=201;#define inf 1000000000int max_flow(int n,int mat[][maxn],int source,int sink){ int v[maxn],c[maxn],p[maxn],ret=0,i,j; for(;;){ for(i=0;in;i++) v[i]=c[i]=0; for(c[source]=inf;;){ for(j=-1,i=0;in;i++) if(!v[i]c[i](j==-1||c[i]c[j])) j=i; if(j0) return ret; if(j==sink) break; for(v[j]=1,i=0;in;i++) if(mat[j][i]c[i]c[j]c[i]) c[i]=mat[j][i]c[j]?mat[j][i]:c[j],p[i]=j; } for(ret+=j=c[i=sink];i!=
文档评论(0)