题意:给定网络求最大流
为什么要建反向边?
因为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));
}
}