图论: 最小费用最大流

来源:互联网 发布:麻瓜编程 爬虫 编辑:程序博客网 时间:2024/06/01 10:38
                                                      最小费用最大流问题
问题描述:
              在最大流的问题上面, 加上了费用:假设每条边除了有一个流量的限制外 , 还有一个单位流量的费用.
         即: 给出最大流量的前提下, 还要附加上最小费用. 这就是最小费用最大流问题.
问题解析:
               在此问题下, 你会发想平行边变得有意义了 , 可能会从u到v的弧 , 费用分别会是w1,w2 . 之前我们是
        可以将它们合并的. 现在我们无法将它们合并了. 为什么?因为若e(u,v) , e(v,u)同时存在, 且费用都是负数
        代表: 从u流向v的 和 从v流向u的.这个问题我们可以通过临接表巧妙的解决.
        另外我们规定: cost(u,v) + cost(v,u) = 0. 代表反向增广时是减小费用.
 实现方法:
        spfa算法 + 临接表
        spfa算法 + 临接矩阵
代码:
临接表:
bool spfa(int start,int end)
{
 

   intdist[MAX];
   queue<int>qu;
   
   p[start] = -1;
   qu.push(start);
   vis[start] = true;
   
   
   for(int i = 0; i <= n+2;++i)
   {
      dist[i] = (i == start ? 0 : INF);
   }
   
   while( !qu.empty() )
   {
      int k = qu.front();
      qu.pop();
      vis[k] = false;
      
      for(int e = first[k]; e != -1; e =edges[e].next)
      {
         if(edges[e].f > 0&& dist[edges[e].v]> dist[k] + edges[e].w)
         {
            dist[edges[e].v] = dist[k] +edges[e].w;
            p[edges[e].v] = e;
            if(!vis[edges[e].v])
            {
               vis[edges[e].v] = true;
               qu.push(edges[e].v);
            }
         }
      }
   }
   
   if(dist[end] < INF)
      return true;
   else
      return false;
   
}

int result()
{
   int minflow = INF;
   for(int i = p[n+1]; i != -1; i =p[edges[i].u])
   {
      if(minflow >edges[i].f)
         minflow = edges[i].f;
   }
   
   for(int i = p[n+1]; i != -1; i =p[edges[i].u])
   {
      edges[i].f -= minflow;
      edges[i^1].f += minflow;
      mincost += edges[i].w * minflow;
   }
}





临接矩阵 :
bool spfa()
{

  queue<int> qu;
   memset(vis,false,sizeof(vis));
   memset(p,-1,sizeof(p));
   for(int i = 1; i <=num_man+num_house+1; ++i)
      dist[i] = (i == start ? 0 : INF);
   vis[start] = true;
   qu.push(start);
   
   while( !qu.empty() )
   {
      int u = qu.front();
      qu.pop();
      vis[u] = false;
      
      for(int v = 1; v <=num_man+num_house+1; ++v)
      {
         if(cap[u][v] > flow[u][v]&& dist[v] > dist[u]+ cost[u][v])
         {
            dist[v] = dist[u] + cost[u][v];
            p[v] = u;
            if( !vis[v] )
            {
               vis[v] = true;
               qu.push(v);
            }
         }
      }
   }
   if(dist[end] >= INF)
      return false;
   else
      return true;
   
}

void solve()
{
   int minflow;
   while(true)
   {
      if(!spfa())
         break;
      minflow = INF;
      for(int u = end; u != start; u =p[u])
      {
         minflow = min(minflow,cap[p[u]][u] -flow[p[u]][u]);
      }
      for(int u = end; u != start; u =p[u])
      {
         flow[p[u]][u] += minflow;
         flow[u][p[u]] -= minflow;
         
      }
      result += dist[end]*minflow;
   }
}



0 0
原创粉丝点击