最小费用最大流模板

来源:互联网 发布:k开头的网络用语 编辑:程序博客网 时间:2024/06/05 00:09
//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:ausing 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);  //找到这条扩展路径中最小的capmaxflow+=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;}

0 0
原创粉丝点击