zoukankan      html  css  js  c++  java
  • poj 2135最小费用最大流

    最小费用最大流问题是经济学和管理学中的一类典型问题。在一个网络中每段路径都有“容量”和“费用”两个限制的条件下,此类问题的研究试图寻找出:流量从A到B,如何选择路径、分配经过路径的流量,可以在流量最大的前提下,达到所用的费用最小的要求。如n辆卡车要运送物品,从A地到B地。由于每条路段都有不同的路费要缴纳,每条路能容纳的车的数量有限制,最小费用最大流问题指如何分配卡车的出发路径可以达到费用最低,物品又能全部送到。

    #include<stdio.h>

    #include<queue>
    #include<iostream>
    #define inf  999999999
    using namespace std;
    #define N 11000
    struct node {
    int u,v,c,f,next;
    }bian[N*4];
    int dis[N],yong,head[N],sum,pre[N],n;
    void Ad(int u,int v,int c,int f) {
    bian[yong].u=u;
    bian[yong].v=v;
    bian[yong].c=c;//权值
    bian[yong].f=f;//能用几次
    bian[yong].next=head[u];//head数组用来记录上一个边的下标
    head[u]=yong++;//当前边的下标
    }
    void Add(int u,int v,int c,int f) {
    Ad(u,v,c,f);
    Ad(v,u,-c,0);
    }
    int spfa(int s,int t) {//单源最短路采取的方法是动态逼近法:设立一个先进先出的队列用来保存待优化的结点,优化时每次取出队首结点u,并且用u点当前的最短路径估计值对离开u点所指向的结点v进行松弛操作,如果v点的最短路径估计值有所调整,且v点不在当前的队列中,就将v点放入队尾。这样不断从队列中取出结点来进行松弛操作,直至队列空为止。
    //定理: 只要最短路径存在,上述SPFA算法必定能求出最小值。
    //证明:每次将点放入队尾,都是经过松弛操作达到的。换言之,每次的优化将会有某个点v的最短路径估计值d[v]变小。所以算法的执行会使d越来越小。由于我们假定图中不存在负权回路,所以每个结点都有最短路径值。因此,算法不会无限执行下去,随着 d值的逐渐变小,直到到达最短路径值时,算法结束,这时的最短路径估计值就是对应结点的最短路径值


    int i,visit[N],cur;
    memset(pre,-1,sizeof(pre));
    memset(visit,0,sizeof(visit));
    for(i=0;i<=n+1;i++)
    dis[i]=inf;
    queue<int>q;
    dis[0]=0;
    q.push(0);
    visit[0]=1;
    while(!q.empty()) {
           cur=q.front();
      q.pop();
      for(i=head[cur];i!=-1;i=bian[i].next) {//因为0是在建所有有效边之后故将所有的边都依次加入
     int  v=bian[i].v;
      if(bian[i].f&&dis[v]>dis[cur]+bian[i].c) {//加了点cur之后进行路径松弛
      dis[v]=dis[cur]+bian[i].c;
      pre[v]=i;//记录当前点连接的边的下标
      if(visit[v]==0) {//dis[v]已经有所改变如果不在队列里就把它放到队尾
      visit[v]=1;
      q.push(v);
      }
      }
      }
      visit[cur]=0;
      }
    if(dis[t]==inf)
    return 0;
    return  1;
    }
    void cou(int t) {
    int i,j;
    i=pre[t];//连接t的边进而可以得出连接t的点
    while(i!=-1) {
    j=i^1;
    bian[i].f--;
    bian[j].f++;
    sum+=bian[i].c;
    i=pre[bian[i].u];//bian[i].u连接的边
    }
    }
    int main() {
    int m,a,b,c;
    while(scanf("%d%d",&n,&m)!=EOF) {
    yong=0;
    memset(head,-1,sizeof(head));
    while(m--) {
    scanf("%d%d%d",&a,&b,&c);
    Add(a,b,c,1);
    Add(b,a,c,1);
    }
    Add(0,1,0,2);
    Add(n,n+1,0,2);
    sum=0;
    while(spfa(0,n+1))  {
     cou(n+1);
    }
    printf("%d ",sum);
    }
    return 0;
    }
  • 相关阅读:
    iOS UI调试神器,插件injection for Xcode使用方法
    iOS 开发笔记-Objective-C之KVC、KVO
    iOS 测试企业应用的分发
    iOS 阅读唐巧博客心得
    iOS 添加启动图片
    Xcode 常用命令
    iOS 开发笔记
    iOS 开发常用链接总结
    iOS
    iOS UI基础
  • 原文地址:https://www.cnblogs.com/thefirstfeeling/p/4410877.html
Copyright © 2011-2022 走看看