重庆分公司,新征程启航

为企业提供网站建设、域名注册、服务器等服务

java网络流最大流代码 java 网络流

java httpserveletresponse文件流最大是多少

ServletResponse中定义了如下两个方法

专业成都网站建设公司,做排名好的好网站,排在同行前面,为您带来客户和效益!成都创新互联公司为您提供成都网站建设,五站合一网站设计制作,服务好的网站设计公司,网站设计、成都网站建设负责任的成都网站制作公司!

getOutputStream();

getWriter();

对应获得字节流和字符流

由于HttpServletResponse继承自ServletResponse所以天生也具有以上两个获得输出流的方法

怎么样求网络的最大流和最小截集

首先是网络流中的一些定义:

V表示整个图中的所有结点的集合.

E表示整个图中所有边的集合.

G = (V,E) ,表示整个图.

s表示网络的源点,t表示网络的汇点.

对于每条边(u,v),有一个容量c(u,v) (c(u,v)=0),如果c(u,v)=0,则表示(u,v)不存在在网络中。相反,如果原网络中不存在边(u,v),则令c(u,v)=0.

对于每条边(u,v),有一个流量f(u,v).

一个简单的例子.网络可以被想象成一些输水的管道.括号内右边的数字表示管道的容量c,左边的数字表示这条管道的当前流量f.

网络流的三个性质:

1、容量限制: f[u,v]=c[u,v]

2、反对称性:f[u,v] = - f[v,u]

3、流量平衡: 对于不是源点也不是汇点的任意结点,流入该结点的流量和等于流出该结点的流量和。

只要满足这三个性质,就是一个合法的网络流.

最大流问题,就是求在满足网络流性质的情况下,源点 s 到汇点 t 的最大流量。

求一个网络流的最大流有很多算法 这里首先介绍 增广路算法(EK)

学习算法之前首先看了解这个算法中涉及到的几个图中的定义:

**残量网络

为了更方便算法的实现,一般根据原网络定义一个残量网络。其中r(u,v)为残量网络的容量。

r(u,v) = c(u,v) – f(u,v)

通俗地讲:就是对于某一条边(也称弧),还能再有多少流量经过。

Gf 残量网络,Ef 表示残量网络的边集.

这是上面图的一个残量网络。残量网络(如果网络中一条边的容量为0,则认为这条边不在残量网络中。

r(s,v1)=0,所以就不画出来了。另外举个例子:r(v1,s) = c(v1,s) – f(v1,s) = 0 – (-f(s,v1)) = f(s,v1) = 4.

其中像(v1,s)这样的边称为后向弧,它表示从v1到s还可以增加4单位的流量。

但是从v1到s不是和原网络中的弧的方向相反吗?显然“从v1到s还可以增加4单位流量”这条信息毫无意义。那么,有必要建立这些后向弧吗?

显然,第1个图中的画出来的不是一个最大流。

但是,如果我们把s - v2 - v1 - t这条路径经过的弧的流量都增加2,就得到了该网络的最大流。

注意到这条路径经过了一条后向弧:(v2,v1)。

如果不设立后向弧,算法就不能发现这条路径。

**从本质上说,后向弧为算法纠正自己所犯的错误提供了可能性,它允许算法取消先前的错误的行为(让2单位的流从v1流到v2)

注意,后向弧只是概念上的,在程序中后向弧与前向弧并无区别.

**增广路

增广路定义:在残量网络中的一条从s通往t的路径,其中任意一条弧(u,v),都有r[u,v]0。

如图绿色的即为一条增广路。

看了这么多概念相信大家对增广路算法已经有大概的思路了吧。

**增广路算法

增广路算法:每次用BFS找一条最短的增广路径,然后沿着这条路径修改流量值(实际修改的是残量网络的边权)。当没有增广路时,算法停止,此时的流就是最大流。

**增广路算法的效率

设n = |V|, m = |E|

每次增广都是一次BFS,效率为O(m),而在最坏的情况下需要(n-2增广。(即除源点和汇点外其他点都没有连通,所有点都只和s与t连通)

所以,总共的时间复杂度为O(m*n),所以在稀疏图中效率还是比较高的。

hdoj 1532是一道可以作为模板题目练手。

模板代码:

[cpp] view plain copy print?

#include cstdio

#include cstring

#include iostream

#include string

#include algorithm

#include map

#include vector

using namespace std;

const int N = 1100;

const int INF = 0x3f3f3f3f;

struct Node

{

int to;//终点

int cap; //容量

int rev; //反向边

};

vectorNode v[N];

bool used[N];

void add_Node(int from,int to,int cap) //重边情况不影响

{

v[from].push_back((Node){to,cap,v[to].size()});

v[to].push_back((Node){from,0,v[from].size()-1});

}

int dfs(int s,int t,int f)

{

if(s==t)

return f;

used[s]=true;

for(int i=0;iv[s].size();i++)

{

Node tmp = v[s][i]; //注意

if(used[tmp.to]==false tmp.cap0)

{

int d=dfs(tmp.to,t,min(f,tmp.cap));

if(d0)

{

tmp.cap-=d;

v[tmp.to][tmp.rev].cap+=d;

return d;

}

}

}

return 0;

}

int max_flow(int s,int t)

{

int flow=0;

for(){

memset(used,false,sizeof(used));

int f=dfs(s,t,INF);

if(f==0)

return flow;

flow+=f;

}

}

int main()

{

int n,m;

while(~scanf("%d%d",n,m))

{

memset(v,0,sizeof(v));

for(int i=0;in;i++)

{

int x,y,z;

scanf("%d%d%d",x,y,z);

add_Node(x,y,z);

}

printf("%d\n",max_flow(1,m));

}

}

最大网络流问题 ,谁能帮我把题目的代码写一下,用c++或c写。题目如下:

#includeiostream

#includequeue

using namespace std;

#define INF 1000000000

struct node{

int from;

int to;

int flow;

}f[1000];

int n,m;

int maxf[1000];

bool vis[1000];

void bfs()

{

queueint p;

int i;

vis[1]=true;

p.push(1);

while(!p.empty())

{

int q=p.front();

p.pop();

for(i=1;i=m;i++)

{

if(f[i].from==q)

{

if(vis[f[i].to]==0)

{

p.push(f[i].to);

vis[f[i].to]=true;

}

maxf[f[i].to]+=min(f[i].flow,maxf[q]);

}

}

}

coutmaxf[n]endl;

}

int main()

{

while(cinnm)

{

int i;

for(i=1;i=m;i++)

{

cinf[i].fromf[i].tof[i].flow;

}

memset(maxf,0,sizeof(maxf));

memset(vis,0,sizeof(vis));

maxf[1]=INF;

bfs();

}

return 0;

}

BFS解最大流。

网络流的最大流算法

1、augment path,直译为“增广路径”,其思想大致如下:

原有网络为G,设有一辅助图G',其定义为V(G') = V(G),E(G')初始值(也就是容量)与E(G)相同。每次操作时从Source点搜索出一条到Sink点的路径,然后将该路径上所有的容量减去该路径上容量的最小值,然后对路径上每一条边u,v添加或扩大反方向的容量,大小就是刚才减去的容量。一直到没有路为止。此时辅助图上的正向流就是最大流。

我们很容易觉得这个算法会陷入死循环,但事实上不是这样的。我们只需要注意到每次网络中由Source到Sink的流都增加了,若容量都是整数,则这个算法必然会结束。

寻找通路的时候可以用DFS,BFS最短路等算法。就这两者来说,BFS要比DFS快得多,但是编码量也会相应上一个数量级。

增广路方法可以解决最大流问题,然而它有一个不可避免的缺陷,就是在极端情况下每次只能将流扩大1(假设容量、流为整数),这样会造成性能上的很大问题,解决这个问题有一个复杂得多的算法,就是预推进算法。

2、push label,直译为“预推进”算法。

3、压入与重标记(Push-Relabel)算法

除了用各种方法在剩余网络中不断找增广路(augmenting)的Ford-Fulkerson系的算法外,还有一种求最大流的算法被称为压入与重标记(Push-Relabel)算法。它的基本操作有:压入,作用于一条边,将边的始点的预流尽可能多的压向终点;重标记,作用于一个点,将它的高度(也就是label)设为所有邻接点的高度的最小值加一。Push-Relabel系的算法普遍要比Ford-Fulkerson系的算法快,但是缺点是相对难以理解。

Relabel-to-Front使用一个链表保存溢出顶点,用Discharge操作不断使溢出顶点不再溢出。Discharge的操作过程是:若找不到可被压入的临边,则重标记,否则对临边压入,直至点不再溢出。算法的主过程是:首先将源点出发的所有边充满,然后将除源和汇外的所有顶点保存在一个链表里,从链表头开始进行Discharge,如果完成后顶点的高度有所增加,则将这个顶点置于链表的头部,对下一个顶点开始Discharge。

Relabel-to-Front算法的时间复杂度是O(V^3),还有一个叫Highest Label Preflow Push的算法复杂度据说是O(V^2*E^0.5)。我研究了一下HLPP,感觉它和Relabel-to-Front本质上没有区别,因为Relabel-to-Front每次前移的都是高度最高的顶点,所以也相当于每次选择最高的标号进行更新。还有一个感觉也会很好实现的算法是使用队列维护溢出顶点,每次对pop出来的顶点discharge,出现了新的溢出顶点时入队。

Push-Relabel类的算法有一个名为gap heuristic的优化,就是当存在一个整数0kV,没有任何顶点满足h[v]=k时,对所有h[v]k的顶点v做更新,若它小于V+1就置为V+1。

cpp程序: #includecstdio#includecstring#includealgorithm#includequeue#define inf 0x7fffffffusingnamespace std;int tt,kase;int nn,m;int H[45],X[1004],P[1004],flow[1004],tot,cap[1005];int d[45];int S,T;void add(int x,int y,int z){P[++tot]=y;X[tot]=H[x];H[x]=tot;flow[tot]=z;cap[tot]=flow[tot];}queueint q;bool bfs(){memset(d,0,sizeof(d));d[S]=1; int x;q.push(S);while(!q.empty()){x=q.front();q.pop();for(int i=H[x];i;i=X[i]){if(flow[i]0!d[P[i]]){d[P[i]]=d[x]+1;q.push(P[i]);}}}returnd[T];}int dfs(int x,int a){if(x==T||a==0)return a;int f=a,tmp;for(int i=H[x];i;i=X[i]){if(flow[i]0d[P[i]]==d[x]+1){tmp=dfs(P[i],min(flow[i],a));flow[i]-=tmp;a-=tmp;flow[i^1]+=tmp;if(!a)break;}}if(f==a)d[x]=-1;return f-a;}int Dinic(){int f=0;while(bfs())f+=dfs(S,inf);return f;}int main(){/**输入过程省略**/int maxflow=Dinic();printf(%d\n,maxflow);return 0;}


当前名称:java网络流最大流代码 java 网络流
标题路径:http://cqcxhl.com/article/ddeephg.html

其他资讯

在线咨询
服务热线
服务热线:028-86922220
TOP