最大流(EK模版)——HDOJ 3549

来源:互联网 发布:php邮箱验证激活码 编辑:程序博客网 时间:2024/06/08 18:17

HDOJ 3549 Flow Problem

这道题目可以作为最大流算法的模版,也是最简单的最大流题目之一

/*HDOJ 3549 Flow Problem最大流,第一道题目,纯粹是理解EK算法*/#include <iostream>#include <queue>using namespace std;#define min(a,b) (a)<(b)?a:b#define N 16int capacity[N][N]; //容量int flow[N]; //残余容量int pre[N]; //前驱结点int n,m;queue<int> qu;int BFS(int src,int des){while(!qu.empty())qu.pop();for(int i=1;i<=n;i++)pre[i]=-1;pre[src]=0;flow[src]=INT_MAX; //初始化源点的流量为无穷qu.push(src);while(!qu.empty()){int index=qu.front();qu.pop();if(index == des)break;for(i=1;i<=n;i++){if(i!=src && capacity[index][i]>0 && pre[i] == -1){pre[i]=index;flow[i]=min(capacity[index][i],flow[index]);//一步步找出增广路径中的最小的可增加流量qu.push(i);}}}if(pre[des] == -1)return -1; //不存在增广路径return flow[des];}int MaxFlow(int src,int des){int aug=0;int sumflow=0;while((aug=BFS(src,des)) != -1){int k=des;while(k!=src){int last=pre[k];capacity[last][k] -= aug;capacity[k][last] += aug;k=last;}sumflow += aug;}return sumflow;}int main(){int nCase,cas=1;cin>>nCase;while(nCase--){cin>>n>>m;memset(capacity,0,sizeof(capacity));memset(flow,0,sizeof(flow));for(int i=0;i<m;i++){int u,v,w;cin>>u>>v>>w;if(u == v)continue;capacity[u][v] +=w;}cout<<"Case "<<cas++<<": "<<MaxFlow(1,n)<<endl;}return 0;}

下面是邻接表的实现

#include <iostream>using namespace std;#define min(a,b) (a)<(b)?a:b#define NV 16#define NE 2000struct Edge{int e;int w;int next;}edge[NE];int head[NV];int pre[NV];int cur[NV];int que[NV],front,rear;int n,edgesum,m;inline void init(int x){n=x;edgesum=0;for(int i=0;i<=n;i++)head[i]=-1;}inline void insert(int s,int e,int w){edge[edgesum].e=e;edge[edgesum].w=w;edge[edgesum].next=head[s];head[s]=edgesum++;edge[edgesum].e=s;edge[edgesum].w=0;edge[edgesum].next=head[e];head[e]=edgesum++;}int MaxFlow(int src,int des){int maxflow=0;while(1){memset(pre,-1,sizeof(pre));que[front=rear=0]=src;while(front <= rear){int u=que[front++];for(int i=head[u];i != -1;i=edge[i].next){int e=edge[i].e;if(pre[e] == -1 && edge[i].w>0){pre[e]=u;que[++rear]=e;cur[e]=i;}}if(pre[des] != -1)break; //已经找到一条增广路径}if(pre[des] == -1)break;int aug=INT_MAX;for(int v=des;v!=src;v=pre[v])aug=min(aug,edge[cur[v]].w);for(v=des;v!=src;v=pre[v]){edge[cur[v]].w -= aug;edge[cur[v]^1].w += aug;  //这里用异或运算,是因为正反两条边刚好是一前一后的}maxflow += aug;}return maxflow;}int main(){int cas=1,nCase;cin>>nCase;while (nCase--){cin>>n>>m;init(n);while(m--){int u,v,w;cin>>u>>v>>w;if(u == v)continue;insert(u,v,w);}cout<<"Case "<<cas++<<": ";cout<<MaxFlow(1,n)<<endl;}return 0;}