//MCMF邻接表模板,邻接矩阵的模板,只需要pre就可以了,不要pos了
#include<cstdio>
#include<cstring>
#include<queue>
#define MAXN 100
#define MAXE 10000
#define INF 0x7fffffff
#define MIN(a,b) a>b?b:a
using namespace std;
int head[MAXN],dist[MAXN],vist[MAXN],pre[MAXN],pos[MAXN];
//head邻接表的表头,dist记录点v到源点st的最小费用
//vist记录顶点是否被访问,pre记录当前点的前驱,pos记录当前边(u,v)的序号
int cnt;
int st,ed;//源点,汇点
int mincost,maxflow;
struct Edge
{
int to;
int cap;
int cost;
int next;
}edge[MAXE];
void add(int u,int v,int cap,int cost)
{
edge[cnt].to=v;
edge[cnt].cap=cap; //正向边的容量
edge[cnt].cost=cost; //正向边的花费
edge[cnt].next=head[u];
head[u]=cnt++;
edge[cnt].to=u;
edge[cnt].cap=0; //反向边的容量为0
edge[cnt].cost=-cost; //反向边的花费为-cost
edge[cnt].next=head[v];
head[v]=cnt++;
}
void MCMF(int st,int ed)
{
int i,u,v;
int aug;
mincost=maxflow=0;
for(;;)
{
memset(vist,0,sizeof(vist));
memset(pre,-1,sizeof(pre));
//memset(dist,INF,sizeof(dist));
//memset赋值时,容易溢出变负数,一晚上错这里了!!!
for(i=0;i<=ed;i++)
dist[i]=INF;
dist[st]=0;
pre[st]=st;
vist[st]=1;
queue<int> q;
q.push(st);
while(!q.empty())
{
u=q.front();
q.pop();
vist[u]=0;
for(i=head[u];i!=-1;i=edge[i].next)
{
v=edge[i].to;
if(edge[i].cap>0&&dist[v]>dist[u]+edge[i].cost)
{
dist[v]=dist[u]+edge[i].cost;
pre[v]=u; //记录当前节点的前驱节点
pos[v]=i; //记录当前边(u,v)的序号
if(!vist[v])
{
vist[v]=1;
q.push(v);
}
}
}
}//SPFA
//if(pre[ed]==-1)
if(dist[ed]==INF) //这两个判断条件是等价的
break;
aug=INF;
for(u=ed;u!=st;u=pre[u])
aug=MIN(aug,edge[pos[u]].cap); //找到这条扩展路径中最小的cap
maxflow+=aug; //最大流增加
mincost+=dist[ed]*aug; //最小费用增加
for(u=ed;u!=st;u=pre[u]) //更新网络
{
edge[pos[u]].cap-=aug;
edge[pos[u]^1].cap+=aug;
}
}
}
int main()
{
st=0;
ed=n+1;
//add(,,,)
//建图过程略
MCMF(st,ed);
printf("%d\n",mincost);
printf("%d\n",maxflow);
return 0;
}
最小费用最大流模板
最新推荐文章于 2022-03-12 09:15:35 发布