网络流最大流算法(ISAP算法及DINIC算法)
2016-08-24 19:25
363 查看
这些算法网络中解释都有,所有以下是根据题目应用,代码中有注释,方便理解,ISAP算法就是通过先bfs一遍建立逆序求层数,然后每次都进行维护求最短路来求增广路径,下次查找建立在上次查找的最小路径的源点进行继续查找,DINIC即是通过顺序,每次找最短路径前都进行一次层次的划分(相当于先找出这次查找可能的最小路径长度),再来求最短路增广路径,直至无法划分层次出现断层。下面用两个方法来做这道题,可以作为模板使用
题目:http://acm.split.hdu.edu.cn/showproblem.php?pid=4280
题意:有N个岛屿,M条路线,每条路线连接两个岛屿,并且每条路有最大客流量,这是无向的,就是可以过去也可以回来,现在求最西边到最东边的岛屿,最多有多少人可以过去,每次保证最东边和最西边岛屿只有一个。显示输入N行x,y左边,后面接着路线和客流量
题解:裸算法,直接求即可,ISAP比较好,时间快
代码:
ISAP算法
DINIC算法
题目:http://acm.split.hdu.edu.cn/showproblem.php?pid=4280
题意:有N个岛屿,M条路线,每条路线连接两个岛屿,并且每条路有最大客流量,这是无向的,就是可以过去也可以回来,现在求最西边到最东边的岛屿,最多有多少人可以过去,每次保证最东边和最西边岛屿只有一个。显示输入N行x,y左边,后面接着路线和客流量
题解:裸算法,直接求即可,ISAP比较好,时间快
代码:
ISAP算法
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<queue> #define DIAN_MAX 435050 #define BIAN_MAX 435050 #define INF 0xfffffff using namespace std; typedef struct { int from,tail,cost,next; }Edge; int n,m;//n为点的数量,m为边的数量 Edge edge[BIAN_MAX]; //邻接表存储边 int ecount; //存储边的当前位置 int head[DIAN_MAX]; //点头数组 int copyhead[DIAN_MAX];//head的复制版 int layer[DIAN_MAX]; //层次数组 int gap[DIAN_MAX]; //gap,用于优化该算法,只要出现断层,就说明该算法可以结束了 int myqueue[DIAN_MAX]; //自定义的队列 int start,tail; //开始点和终止点 int edgestack[DIAN_MAX]; //自定义栈,用于存放一条起始点到终点的最短路路径 void addEdge(int s,int e,int cost)//针对无向和有向皆可 { edge[ecount].from=s; edge[ecount].tail=e; edge[ecount].cost=cost; edge[ecount].next=head[s]; head[s]=ecount++; //反向路径,用于后悔的情况 edge[ecount].from=e; edge[ecount].tail=s; edge[ecount].cost=0; edge[ecount].next=head[e]; head[e]=ecount++; } void bfs() //先进行bfs来分层,逆序来求层次,从最终点到起始点,最终点层次为0 { memset(gap,0,sizeof(gap)); memset(layer,-1,sizeof(layer)); int first=0,last=0,i,now,next; myqueue[last++]=tail; gap[0]=1; //表示第0层次存在1个点 同理推i layer[tail]=0; //表示第tail点层次为1 while(first<last) { now=myqueue[first++]; first=first%DIAN_MAX; for(i=head[now];i!=-1;i=edge[i].next) { next=edge[i].tail; //逆推层次 if(edge[i].cost!=0||layer[next]!=-1) continue; myqueue[last++]=next; last=last%DIAN_MAX; layer[next]=layer[now]+1; gap[layer[next]]++; } } } int ISAP() { int ans=0; bfs(); memcpy(copyhead,head,sizeof(head)); int top=0,now=start,i,minn,op; while(layer[start]<n) { if(now==tail)//这种情况即表示已经找到了从开始点到终点的一条路径 { minn=INF; for(i=0;i<top;i++)//找出路径中的最小距离,用于更新其他路径 { if(minn>edge[edgestack[i]].cost) { minn=edge[edgestack[i]].cost; op=i; } } ans+=minn; //用最小路径更新 for(i=0;i<top;i++) { edge[edgestack[i]].cost-=minn; edge[edgestack[i]^1].cost+=minn; } //用最小路径的起始点来更新接下来要找的起始点, //因为减去的边是最小的,所以前面边一定没有剪成0,免去了从新遍历 top=op; now=edge[edgestack[top]].from; } //当出现断层时就直接结束,即从S无法到到T集合 if(now!=tail&&gap[layer[now]-1]==0) { break; } //找出层次差1即相邻,并且路径剩余量不为0的边 for(i=copyhead[now];i!=-1;i=edge[i].next) { if(edge[i].cost!=0&&layer[now]==layer[edge[i].tail]+1) break; } //若存在,就记录下点然后继续查找 if(i!=-1) { copyhead[now]=i; edgestack[top++]=i; now=edge[i].tail; } //若不存在,更新现在已经排除的路径,免得之后再找 else { //找出相邻的层次最小的点,该点可以到达此点,所以这点最小层次为找到的最小值+1 minn=n; for(i=head[now];i!=-1;i=edge[i].next) { if(edge[i].cost<=0) continue; if(minn>layer[edge[i].tail]) {minn=layer[edge[i].tail];copyhead[now]=i;} } //更新代数的数量 gap[layer[now]]--; layer[now]=minn+1; gap[minn+1]++; //从上一个点继续查找 if(now!=start) now=edge[edgestack[--top]].from; } } return ans; } int main() { int t; scanf("%d",&t); while(t--) { memset(head,-1,sizeof(head)); ecount=0; scanf("%d %d",&n,&m); int minn=1000000; int maxx=-1000000; for(int i=1;i<=n;i++) { int x,y; scanf("%d %d",&x,&y); if(x<minn){minn=x;start=i;} else if(x>maxx){maxx=x;tail=i;} } for(int i=0;i<m;i++) { int s,d,w; scanf("%d %d %d",&s,&d,&w); addEdge(s,d,w); addEdge(d,s,w); } printf("%d\n",ISAP()); } return 0; }
DINIC算法
#include<iostream> #include<cstdio> #include<cstring> #include<string> #define BIAN_MAX 400050 #define DIAN_MAX 100050 #define INF 0xfffffff using namespace std; int n,m; int start,tail; typedef struct { int from,to,cost,next; }Edge; Edge edge[BIAN_MAX]; int myqueue[BIAN_MAX]; int ecount; int head[DIAN_MAX]; int layer[DIAN_MAX]; void init() { memset(head,-1,sizeof(head)); ecount=0; } void addedge (int u, int v, int flow) { edge[ecount].to = v; edge[ecount].next = head[u]; edge[ecount].cost = flow; head[u] = ecount++; swap (u, v); edge[ecount].to = v; edge[ecount].next = head[u]; edge[ecount].cost = flow; head[u] = ecount++; } bool bfs()//每次更新代数,即是找到最小的从起始到终点的距离,每次从起始点开始 { memset(layer,0,sizeof(layer)); int first=0,last=0,i,next,now; layer[start] = 1; myqueue[last++]=start; while(first<last) { now=myqueue[first++]; if(now==tail) return 1;//若找到了最后一点,直接返回,说明已经找到 first=first%BIAN_MAX; for(i=head[now];i!=-1;i=edge[i].next) { next=edge[i].to; //每次保证该点没有查找过并且有距离余额 if(!layer[next]&&edge[i].cost>0) { layer[next]=layer[now]+1; if(next==tail) return 1; myqueue[last++]=next; last%=BIAN_MAX; } } } return 0; } //通过层次来查找最短的路径 int dfs(int s,int limit) { if(s==tail) return limit; int cost=0; for(int i=head[s];i!=-1;i=edge[i].next) { int next=edge[i].to; if(layer[next]==layer[s]+1&&edge[i].cost>0) { int tmp=dfs(next,min(limit-cost,edge[i].cost)); edge[i].cost-=tmp; edge[i^1].cost+=tmp; cost+=tmp; if(cost==limit) break; } } //优化,当这点不能到任意一点时,排除其他点到这点 if(!cost) layer[s]=0; return cost; } int dinic() { int ans=0; while(bfs()) { ans+=dfs(start,INF); } return ans; } int main() { int t; scanf("%d",&t); while(t--) { init(); scanf("%d %d",&n,&m); int minn=1000000,maxx=-1000000; for(int i=1;i<=n;i++) { int x,y; scanf("%d %d",&x,&y); if(x<minn) {minn=x;start=i;} if(x>maxx) {maxx=x;tail=i;} } for(int i=1;i<=m;i++) { int s,e,w; scanf("%d %d %d",&s,&e,&w); addedge(s,e,w); } printf("%d\n",dinic()); } return 0; }
相关文章推荐
- POJ 1273-Drainage Ditches(网络流_最大流_ISAP()算法和EK()算法)
- 网络流入门6—(最大流算法ISAP)
- 网络流初步 增广路算法求最大流 hdoj3549
- HDU3081 Marriage Match II(网络流,最大流,二分,并查集,传递闭包,ISAP)
- BZOJ_P2561 最小生成树(网络流+最大流ISAP)
- 从零单练网络流 第二章 最大流ISAP
- 网络流入门—用于最大流的Dinic算法
- 网络流Ford-fulkerson算法及dinic算法
- poj 1273 hdu 1532 网络流最大流 Dinic算法
- hdu4280 Island Transport (网络流最大流)&(dinic算法模板)
- 最大流(增广算法,预留先推算法,dinic算法)
- poj 1459 Power Network : 最大网络流 dinic算法实现
- 二分图的最大匹配——网络流+匈牙利算法
- 网络流入门—用于最大流的Dinic算法---转载自Comzyh的博客
- fzu1844 Earthquake Damage (网络流 最大流最小割/ISAP)
- POJ3041 二分图最大匹配(网络流算法)
- [译]网络流Dinic算法-最大流-HDU1532&POJ1273
- 网络流--最大流的三大算法
- poj 1459 Power Network : 最大网络流 dinic算法实现
- 【最大流-ISAP】POJ-1273-网络流模板!!