这道题目可以作为最大流算法的模版,也是最简单的最大流题目之一
/*
HDOJ 3549 Flow Problem
最大流,第一道题目,纯粹是理解EK算法
*/
#include <iostream>
#include <queue>
using namespace std;
#define min(a,b) (a)<(b)?a:b
#define N 16
int 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 2000
struct 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;
}