您的位置:首页 > 大数据 > 人工智能

hdu 1532 Drainage Ditches(最大流之Ford-Fulkerson算法)

2015-12-14 00:06 567 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1532

一,概念

1)流网络:简单有向图,且有两个特别的顶点(源点s,汇点t)

2)流的边标识为f(u,v)/c(u,v),流量/容量

3)流的三个性质:1>容量限制 对于所有边 流量<容量

2>反对称性 f(u,v)=-f(v,u)

3>流守恒性 正向流与反响流之和为零

4)割:流网络G=(V,E)的割(S,T)将顶点V划分为S和T=V-S两部分,定义割的容量为C(S)割这条线上S中顶点到T中顶点的容量之和

5)残留网络: 残留容量 c f (u, v) = c(u, v) - f (u, v) //边的容量减去边的实际流量

6)增广路径:对于残留网络 G f 中的一条 s-t 路径 p 称其为增广路径

二,最大流和最小割问题

1)最大流:对于一个流网络 G  (V , E ) ,其流量 f 的最大值称为最大流,最大流问题就

是求一个流网络的最大流。

2)最小割:是指流网络中容量最小的割

Ford-Fulkerson方法是一种迭代的方法。开始时,对所有的u,v∈V有f(u,v)=0,即初始状态时流的值为0。在每次迭代中,可通过寻找一条“增广路径”来增加流值。增广路径可以看成是从源点s到汇点t之间的一条路径,沿该路径可以压入更多的流,从而增加流的值。反复进行这一过程,直至增广路径都被找出来,根据最大流最小割定理,当不包含增广路径时,f是G中的一个最大流。在算法导论中给出的Ford-Fulkerson的伪代码如下:

FORD-FULKERSON(G, s, t)
1 for each edge (u, v) ∈ E[G]
2 do f[u, v] ← 0
3 f[v, u] ← 0
4 while there exists a path p from s to t in the residual network Gf
5 do cf(p) ← min {cf(u, v) : (u, v) is in p}
6 for each edge (u, v) in p
7 do f[u, v] ← f[u, v] + cf(p)
8 f[v, u] ← -f[u, v]


hdu 1532:

#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <sstream>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <list>
#include <set>
//#define ONLINE_JUDGE
#define eps 1e-6
#define INF 0x7fffffff                                          //INT_MAX
#define inf 0x3f3f3f3f                                          //int??????????????????
#define FOR(i,a) for((i)=0;i<(a);(i)++)                          //[i,a);
#define MEM(a) (memset((a),0,sizeof(a)))
#define sfs(a) scanf("%s",a)
#define sf(a) scanf("%d",&a)
#define sfI(a) scanf("%I64d",&a)
#define pf(a) printf("%d\n",a)
#define pfI(a) printf("%I64d\n",a)
#define pfs(a) printf("%s\n",a)
#define sfd(a,b) scanf("%d%d",&a,&b)
#define sft(a,b,c)scanf("%d%d%d",&a,&b,&c)
#define for1(i,a,b) for(int i=(a);i<b;i++)
#define for2(i,a,b) for(int i=(a);i<=b;i++)
#define for3(i,a,b)for(int i=(b);i>=a;i--)
#define MEM1(a) memset(a,0,sizeof(a))
#define MEM2(a) memset(a,-1,sizeof(a))
#define MEM3(a) memset(a,0x3f,sizeof(a))
#define MEMS(a) memset(a,'\0',sizeof(a))
#define LL __int64
const double PI = acos(-1.0);
template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template<class T> T lcm(T a, T b) { return a / gcd(a, b) * b; }
template<class T> inline T Min(T a, T b) { return a < b ? a : b; }
template<class T> inline T Max(T a, T b) { return a > b ? a : b; }
using namespace std;
template<class T>
T Mint(T a, T b, T c) {
if (a>b) {
if (c>b)
return b;
return c;
}
if (c>a)
return a;
return c;
}
template<class T>
T Maxt(T a, T b, T c) {
if (a>b) {
if (c>a)
return c;
return a;
}
else if (c > b)
return c;
return b;
}

const int maxn=1100;
int T,n,m;
int vis[maxn];
int si,ei,ci;

struct node{
int to;//终点
int cap;//容量
int rev;//反向边
};

vector<node>v[maxn];//邻接链表建图

void addEdge(int a,int b,int c){
v[a].push_back((node){b,c,v[b].size()});
v[b].push_back((node){a,0,v[a].size()-1});//添加反向边
}

int dfs(int s,int t,int f){
if(s==t) return f;
vis[s]=1;
for1(i,0,v[s].size()){
node &tmp=v[s][i];
if(!vis[tmp.to]&&tmp.cap>0){
int d=dfs(tmp.to,t,min(f,tmp.cap));
//对边进行缩减,以便将更多的流从源节点发送到汇点
if(d>0){
tmp.cap-=d;//f(u,v)-d
v[tmp.to][tmp.rev].cap+=d;//f'(v,u)+d;
return d;
}
}
}
return 0;
}

//如果残存网络中存在增广路,增加流量
int max_flow(int s,int t){
int flow=0;
while(1){
MEM1(vis);
int f=dfs(s,t,inf);
if(f==0)
return flow;
flow+=f;
}
}

int main(){
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
#endif
while(~sfd(n,m)){
MEM1(v);
for1(i,0,n){
sft(si,ei,ci);
addEdge(si,ei,ci);
}
int ans=max_flow(1,m);
pf(ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: