最小费用流模板

 

 

可以计算负权边的dijkstra

//最小费用流Dijkstra算法

//Dijkstra算法求最小费用流核心代码:

//h[MAX_V]:导入势保证所有边均为非负边 O(FElogV)
int min_cost_flow(int n, int v, int s, int t, int f)
{

   int i, ans = 0;

   fill(h, h + v, 0);

   while(f > 0)    
   {
    //Dijkstra算法:寻找最短路 O(ElogV)
      priority_queue<P, vector<P>, greater<P> > que;
      fill(dis, dis + v, INF);
      dis[0] = 0;
      que.push(P(0, s));
      while(!que.empty())
      {
         P p = que.top();
         que.pop();

         int v = p.second;
         if(dis[v] < p.first)
          continue;
         int size = G[v].size();

         for(i = 0; i < size; ++i)
         {
            edge es = G[v][i];//****
            if(es.cap > 0 && dis[es.to] > dis[v] + es.cost + h[v] - h[es.to])

            {   

               dis[es.to] = dis[v] + es.cost + h[v] - h[es.to]; 

            prevv[es.to] = v;
               preve[es.to] = i;
               que.push(P(dis[es.to], es.to));
            }
       }
    }

    if(dis[t] == INF)
    return -1;
  //更新势
    for(i = 0; i < v; ++i)
     h[i] += dis[i]; 
    int d = f;
    for(i = t; i != s; i = prevv[i])
     d = min(d, G[prevv[i]][preve[i]].cap);
    ans += d * h[t];

    f -= d;  

    for(i = t; i != s; i = prevv[i])
    {
       edge &es =  G[prevv[i]][preve[i]];
       es.cap -= d;
       G[i][es.rev].cap += d;
    }
  }

   return ans;
}
View Code

 

简单易行但是复杂度不稳定的spfa

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;

const int INF=0x7f7f7f7f;
const int MAXN=100000;

struct Edge
{
    int u,v,w,c,next;//u起点,v终点,w容量,c花费,next下一条边
}E[MAXN];
int node,head[MAXN];
int pre[MAXN],cost[MAXN],vis[MAXN];
int s,t;
int n,m,ans1,ans2;

void insert(int u,int v,int w,int c)
{
    E[++node]=(Edge){u,v,w,c,head[u]};
    head[u]=node;
    E[++node]=(Edge){v,u,0,-c,head[v]};
    head[v]=node;
}

bool spfa()
{
    queue<int> Q;
    memset(cost,0x7f,sizeof(cost));
    Q.push(s);
    cost[s]=0;vis[s]=1;
    while(!Q.empty())
    {
        int q=Q.front();Q.pop();
        for(int i=head[q];i;i=E[i].next)
            if(E[i].w&&cost[q]+E[i].c<cost[E[i].v])
            {
                cost[E[i].v]=cost[q]+E[i].c;
                pre[E[i].v]=i;
                if(!vis[E[i].v])
                {
                    Q.push(E[i].v);
                    vis[E[i].v]=1;
                }
            }
        vis[q]=0;
    }
    return cost[t]!=INF;
}

void mcf()
{
    int minn=INF;
    for(int i=pre[t];i;i=pre[E[i].u])
        minn=min(minn,E[i].w);
    for(int i=pre[t];i;i=pre[E[i].u])
    {
        ans2+=minn*E[i].c;
        E[i].w-=minn;
        E[i^1].w+=minn;
    }
    ans1+=minn;
}

int main()
{
    scanf("%d%d%d%d",&n,&m,&s,&t);
    for(int i=1;i<=m;i++)
    {
        int u,v,w,c;
        scanf("%d%d%d%d",&u,&v,&w,&c);
        insert(u,v,w,c);
    }
    while(spfa()) mcf();
    printf("%d %d",ans1,ans2);//ans1最大流 ans2最小费用
    return 0;
}
View Code

 

posted @ 2018-11-01 18:07  yosoro  阅读(171)  评论(0编辑  收藏  举报