hdu 3549 Flow Problem 最大流模板题

题意:给定网络求最大流

为什么要建反向边?

因为EK算法是每次从图中找到能够通过t的最小残量 ,然后将最小残量贡献给答案

残量理解为每条边的容量减去流量 最小残量就是能够从s顺利到达t的最小流量

如果不建立反向边这不一定是最大流

"建了反向边,就是给流量一个“反悔”的机会,取消算法之前的错误行为 "

#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#define Min(a,b) a<b?a:b
using namespace std;
const int maxn = 20;
const int INF = 1<<30;//移位不能超过位数限制 
struct edge
{
	int from,to,flow,cap;
	edge(int from,int to,int cap,int flow):from(from),
	to(to),flow(flow),cap(cap){};
};
int a[maxn],p[maxn];
int n,m;
vector<edge> edges;
vector<int> g[maxn];
void addedge(int from,int to,int cap)
{
	edges.push_back(edge(from,to,cap,0));//存储边 
	edges.push_back(edge(to,from,0,0));//反向边 
	int m=edges.size();
	g[from].push_back(m-2);//能够方便查询邻接边的编号 
	g[to].push_back(m-1);
}
int Maxflow(int s,int t)//s为源点编号  t为汇点编号 
{
	int Flow=0;
	while(1)
	{
		memset(a,0,sizeof(a));
		queue<int> q;
		q.push(s);
		a[s]=INF;
		while(!q.empty())
		{
			int x = q.front();q.pop();
			for(int i=0;i<g[x].size();i++)
			{
				edge &e=edges[g[x][i]];
				if(!a[e.to]&&e.cap>e.flow)
				{
					p[e.to]=g[x][i];
					a[e.to]=Min(a[x],e.cap-e.flow);//找最小的残量 
					q.push(e.to);
					
				}
			}
			if(a[t])break;
		}
		
		if(!a[t])break;//找不到增广路
		for(int i=t;i!=1;i=edges[p[i]].from)
		{
			edges[p[i]].flow+=a[t];//
			edges[p[i]^1].flow-=a[t];//反向边 
		}
		Flow+=a[t];
	}
	return Flow;
}
int main()
{
	int T;
	scanf("%d",&T);
	for(int kcase=0;kcase<T;kcase++)
	{
		int u,v,cap;
		scanf("%d%d",&n,&m);
		for(int i=0;i<=n;i++)
		g[i].clear();
		edges.clear();
		for(int i=0;i<m;i++)
		{
			scanf("%d%d%d",&u,&v,&cap);
			addedge(u,v,cap);
		}
		printf("Case %d: %d\n",kcase+1,Maxflow(1,n));
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值