经典的最大流 POJ 1273

转自百度文库 所以没有连接了。

题意描述:

现在有m个池塘(从1到m开始编号,1为源点,m为汇点),及n条水渠,给出这n条水渠所连接的池塘和所能流过的水量,求水渠中所能流过的水的最大容量.一道基础的最大流题目。http://poj.org/problem?id=1273

参考数据:
输入:
5 4
1 2 40
1 4 20
2 4 20
2 3 30
3 4 10

输出:

50

 

增广路算法Edmonds_Karp

const int N=201;
const int INF=99999999;
int n,m,sum,s,t;//s,t为始点和终点
int flow[N][N],cap[N][N],p[N];
//flow[u][v]为<u,v>的流量,cap[u][v]为<u,v>容量,
//a[i]表示源点s到节点i的路径上的最小残留量、p[i]记录i的前驱

int Min(int a,int b)
{
	return a<=b?a:b;
}
void Edmonds_Karp()
{
	int a[201]={0};
	int i,u,v;
	queue<int> q;//队列 用bfs找增广路径
	while(1)
	{
		memset(a,0,sizeof(a));//每找一次 初始化一次
		a[s]=INF;//s为起始点
		q.push(s);//原点入队
		while(!q.empty())
		{
			u=q.front();
			q.pop();
			for(v=1;v<=m;v++)//m是汇点
			{
				if(!a[v]&&flow[u][v]<cap[u][v])//(流量小于容量与节点v未被访问过)
				{//flow[u][v]:为<u,v>的流量,cap[u][v]为<u,v>容量  流量小于容量
					p[v]=u;//p[i]记录i的前驱
					q.push(v);
					a[v]=Min(a[u],cap[u][v]-flow[u][v]);//s-v路径上的最小残留  原点到v的最小残留
				}
			}
		}
		if(a[m]==0)//找不到增广路径,则当前流已经是最大流  s到m的最小残留量为0
		{
			break;
		}
		sum+=a[m];//流加上
		for(i=m;i!=s;i=p[i])//pi记录的是i的前驱,s为原点
		{
			flow[p[i]][i]+=a[m];//更新正向流量  <u,v> flow[u][v]表示流量 a[m]表示原点s到节点m的最小残留量
			flow[i][p[i]]-=a[m];//更新反向流量
		}
	}
	printf("%d\n",sum);
}
int main()
{
	int v,u,w;
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		s=1;//从1开始
		t=m;//m为汇点
		sum=0;//记录最大流量
		memset(flow,0,sizeof(flow));
		memset(cap,0,sizeof(cap));
		while(n--)
		{
			scanf("%d%d%d",&u,&v,&w);
			cap[u][v]+=w;
		}
		Edmonds_Karp();
	}
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值