您的位置:首页 > 理论基础 > 计算机网络

网络最大流中一般增广路算法(标号法)

2014-05-31 15:25 549 查看
网络最大流主要有两大类求解方法:增广路算法和预流推进算法

一般增广路算法:主要分为初始流为零流和初始流为非零流的情况!后者在标号的时候注意一条边是正向连接还是反向连接;若是反向的连接,那么在调整的时候是减去,若为正向那么在调整的时候是加上!

 


这里就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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息