zoukankan      html  css  js  c++  java
  • POJ 2516 Minimum Cost 【费用流】

    建模比较难想。。

    关键在于我一开始想跑一次网络流把题做出来,但无论如何都建不出来图。后来想到,每个商品是互相独立的,之前的商品如何运输影响不到之后的商品如何运输,所以找到每个商品的最小花费然后加起来就行了。

    想到这里剩下的就好做了。

    #include<iostream>
    #include<deque>
    #include<vector>
    #include<cstring>
    #include<cmath>
    #define INF 2e9
    using namespace std;
    
    int T,ans;
    
    struct edge{
        int v,cap,reverse,cost;
    };
    vector<int> edges[1005];//邻接表 
    vector<edge> bian;//所有的边都存在里面
    
    void addedge(int u,int v,int cost,int cap){//u到v一条边,再加一条反向边 
        edge e;
        e.cap=cap;
        e.v=v;
        e.cost=cost;
        e.reverse=bian.size()+1;//这条边的反边将建在这条边之后(这条边建完后在bian.size()的位置) 
        bian.push_back(e);
        edges[u].push_back(bian.size()-1);
        
        e.cap=0;
        e.v=u;
        e.cost=-cost;
        e.reverse=bian.size()-1;
        bian.push_back(e);
        edges[v].push_back(bian.size()-1);
    }
    
    int dist[1005],pre[1005];//pre[i]代表走的哪条边到的i点 
    
    bool spfa(){
        for(int i=0;i<=T;i++) dist[i]=INF;
        for(int i=0;i<=T;i++) pre[i]=-1;
            
        deque<int> q;
        dist[0]=0; pre[0]=-1; q.push_back(0);
        while( !q.empty() ){
            int u = q.front(); q.pop_front();
            for(int i=0;i<edges[u].size();i++){//所有以u为起点的边的边的索引 
                edge &e = bian[ edges[u][i] ];
                int v=e.v;
                if( e.cap>0 && dist[u]+e.cost<dist[v] ){
                    dist[v] = dist[u]+e.cost;
                    pre[v]=edges[u][i];
                    q.push_back(v);
                }
            }
        }
        
        if(dist[T]==INF) return false;
        return true;
    }
    
    int EK(){
        int max_flow=0;
        while( spfa() ){
            //cout<<"suc"<<endl;
            int u=T,minflow=INF;//在终点位置
            while( u!=0 ){
                edge &e = bian[ pre[u] ];
                minflow=min(minflow,e.cap);
                u = bian[ e.reverse ].v;
            }
            ans+=minflow*dist[T];
            max_flow+=minflow;
            u=T;
            while( u!=0 ){
                edge &e = bian[ pre[u] ];
                e.cap-=minflow;
                bian[ e.reverse ].cap+=minflow;
                u = bian[ e.reverse ].v;
            }
        }
        return max_flow;
    }
    
    int order[55][55],supply[55][55];//order是第i个商家对第j个物品的需求  supply第i个supply对第j个物品的库存 
    
    int main(){
        int n,m,k;        
            
        while(1){
            cin>>n>>m>>k;
            if(n==0 && m==0 && k==0) break;
                
            ans=0;
            
            //supply:1-M  shopkeeper:M+1 - M+N
            T = n+m+1; 
            //k个物品间是相互独立的,所以等于跑k次费用流 
            for(int i=1;i<=n;i++)
                for(int j=1;j<=k;j++) cin>>order[i][j];
            
            for(int i=1;i<=m;i++)
                for(int j=1;j<=k;j++) cin>>supply[i][j];
            
            bool flag=true; 
            for(int k1=1;k1<=k;k1++){//k1个商品 
                bian.clear();
                for(int i=0;i<=T;i++) edges[i].clear();
                
                for(int i=1;i<=n;i++){
                    for(int j=1;j<=m;j++){//第j个供应商给i商店供应k商品的代价 
                        int cost; cin>>cost;
                        addedge(j,m+i,cost,INF);
                    }
                }
                //supply到shop解决了
                for(int i=1;i<=n;i++) addedge(m+i,T,0,order[i][k1]);//shop到汇点
                for(int i=1;i<=m;i++) addedge(0,i,0,supply[i][k1]);
                
                int sum=0;
                for(int i=1;i<=n;i++) sum+=order[i][k1];
                
                if( EK()!=sum ) flag=false;
            }
            if( flag ) cout<<ans<<endl;
            else cout<<"-1"<<endl;
        
        }
        
        return 0;    
    }
  • 相关阅读:
    原生js设置cookie
    vuex数据持久化存储
    export和export default的区别
    userAgent判断是微信还是企业微信
    SVN的使用方法
    Js字符串反转
    通用JS10——一元加和减
    通用JS十——递增/递减操作符
    通用JS9
    @SuppressWarning注解用法
  • 原文地址:https://www.cnblogs.com/ZhenghangHu/p/9531757.html
Copyright © 2011-2022 走看看