网络最大流中一般增广路算法(标号法)
2014-05-31 15:25
549 查看
网络最大流主要有两大类求解方法:增广路算法和预流推进算法
一般增广路算法:主要分为初始流为零流和初始流为非零流的情况!后者在标号的时候注意一条边是正向连接还是反向连接;若是反向的连接,那么在调整的时候是减去,若为正向那么在调整的时候是加上!
这里就poj1149为例写一道网络流中用标号法求解一般增广路的方法;
题目链接:http://poj.org/problem?id=1149
题目的关键在于如何构造一个容量网络!
1)将顾客看做除源点和汇点以外的顶点,并且另外设置两个节点,源点和汇点
2)如果源点和某一个节点的边有重复,那么就将权合并
3)源点和每个猪圈的第一位顾客连边,边的权值为猪圈中猪的数目
4)若顾客j在顾客i之后打开某个猪圈,则边<i,j>的权是+00,原因就是迈克可以调整各个猪圈中猪的数目来最大化限度的满足顾客的要求!
5)每个顾客和汇点之间连边,边的权就是顾客希望买到的猪的数目
一般增广路算法:主要分为初始流为零流和初始流为非零流的情况!后者在标号的时候注意一条边是正向连接还是反向连接;若是反向的连接,那么在调整的时候是减去,若为正向那么在调整的时候是加上!
这里就poj1149为例写一道网络流中用标号法求解一般增广路的方法;
题目链接:http://poj.org/problem?id=1149
题目的关键在于如何构造一个容量网络!
1)将顾客看做除源点和汇点以外的顶点,并且另外设置两个节点,源点和汇点
2)如果源点和某一个节点的边有重复,那么就将权合并
3)源点和每个猪圈的第一位顾客连边,边的权值为猪圈中猪的数目
4)若顾客j在顾客i之后打开某个猪圈,则边<i,j>的权是+00,原因就是迈克可以调整各个猪圈中猪的数目来最大化限度的满足顾客的要求!
5)每个顾客和汇点之间连边,边的权就是顾客希望买到的猪的数目
#include <iostream> #include <cstdio> #include <cstring> #define PIG_HOUSE_COUNT 1005 #define CONSUMER 105 #define INF 30000000 using namespace std; int capacity[CONSUMER][CONSUMER];//每一条边上的容量 int flow[CONSUMER][CONSUMER];//每一条边的实际流量 int source,destination;//起点和终点 void init() { int M,N; int i,j,temp;//temp,数据临时存储 int PigArray[PIG_HOUSE_COUNT];//每个猪圈的猪的数目 int KeyNumber;//每一个人拥有的钥匙数目 int Pre[PIG_HOUSE_COUNT];//这个猪圈上一个的打开者 scanf("%d%d",&M,&N); source=0; destination=N+1; memset(Pre,0,sizeof(Pre)); memset(capacity,0,sizeof(capacity)); memset(flow,0,sizeof(flow)); for(i=0;i<M;i++) scanf("%d",&PigArray[i]); for(i=1;i<=N;i++) { scanf("%d",&KeyNumber); for(j=0;j<KeyNumber;j++) { scanf("%d",&temp); if(Pre[temp]==0) capacity[source][i]=capacity[source][i]+PigArray[temp-1]; else capacity[Pre[temp]][i]=INF; Pre[temp]=i; } scanf("%d",&capacity[i][destination]); } } void ford() { int i,j; int queue[CONSUMER];//模拟队列 int flag[CONSUMER];//标号为-1,表示起点;标号为非负数,表示该节点的上一个节点; int minadd[CONSUMER]; int v;//当前的顶点 int qh,qt,p; minadd[0]=INF; while(1)//对每一次标号---调整后,再重新标号 { for(i=0;i<CONSUMER;i++) flag[i]=-2;//表示还没有标号 flag[0]=-1; qh=0;queue[qh]=0;qt=1; while(qh<qt&&flag[destination]==-2)//用bfs查找邻接点 { v=queue[qh];qh++; for(i=0;i<=destination;i++) { if(flag[i]==-2&&(p=capacity[v][i]-flow[v][i])) { minadd[i]=(minadd[v]<p) ? minadd[v]: p ; flag[i]=v; queue[qt++]=i; } } } if(flag[destination]==-2) break; for(i=flag[destination],j=destination;i!=-1;j=i,i=flag[i]) { flow[i][j]+=minadd[destination];//对这次标号后的一条路进行增广 flow[j][i]=-flow[i][j]; } } for(i=0,p=0;i<destination;i++) p+=flow[i][destination]; printf("%d\n",p); } int main() { init(); ford(); return 0; }
相关文章推荐
- 一般增广路方法求网络最大流(Ford-Fulkerson算法)
- 网络最大流求解 增广路算法
- 网络最大流之一般增广路方法------Ford-Fulkerson
- 最大流的增广路算法比较
- 一般图最大匹配问题-带花树开花算法
- 最大流 - Edmonds-Karp 增广路算法
- 最大流增广路算法
- MaxFlow(最大流增广路算法)
- 网络流 之 一般增广路算法 标号法实现
- 网络流DINIC增广路算法介绍
- Ural 1099 Work Scheduling (一般图的最大匹配:带花树算法)
- Ural1109_Conference(二分图最大匹配/匈牙利算法/网络最大流)
- 算法设计 最大网络流
- 网络最大流增广路模板(EK & Dinic)
- PIGS(最大流_增广路算法)
- 算法艺术——网络最大流 (转自:Rachel-Zhang)
- 最大流ISAP(距离标号最短增广路算法)模板
- 算法艺术——网络最大流
- POJ 1273 Drainage Ditches 一般增广路算法,网络流
- 网络流初步 增广路算法求最大流 hdoj3549