zoukankan      html  css  js  c++  java
  • 多源多汇费用流——poj2516

    网络流的题好难。。感觉有点遭不住了

    这题用矩阵存图,然后把k个物品,每个物品都求一次费用流

    /*
    多源多汇的费用流
    其实是k个费用流 
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define inf 0x3f3f3f3f
    #define maxn 205
    struct Edge{int to,nxt,w,c;}e[maxn<<2];
    int head[maxn],tot,n,m,s,t;
    void init(){}
    void add(int u,int v,int w,int c){}
    
    int sum_need[maxn],sum_offer[maxn];
    int offer[maxn][maxn],need[maxn][maxn],mp[maxn][maxn],cost[maxn][maxn],K,sum,pre[maxn];
    
    int dis[maxn],vis[maxn];
    int spfa(){
        queue<int>q;
        for(int i=0;i<=t;i++){vis[i]=false;dis[i]=inf;}
        
        vis[s]=1;dis[s]=0;q.push(s);
        while(!q.empty()){
            int k=q.front();q.pop();vis[k]=false;
            for(int i=0;i<=t;i++)
                if(mp[k][i] && dis[i]>dis[k]+cost[k][i]){
                    dis[i]=dis[k]+cost[k][i];
                    pre[i]=k;
                    if(!vis[i]){
                        vis[i]=1;
                        q.push(i);
                    }
                }
        }
        
        if(dis[t]!=inf)return 1;
        return 0;
    }
    int fond(){
        int Min=inf,res=0; 
        while(spfa()){
            for(int i=t;i!=s;i=pre[i])
                Min=min(Min,mp[pre[i]][i]);
            for(int i=t;i!=s;i=pre[i]){
                mp[pre[i]][i]-=Min;
                mp[i][pre[i]]+=Min;
                res+=cost[pre[i]][i]*Min;
            }
        }
        return res;
    }
    
    int main(){
        while(cin>>n>>m>>K,n&&m&&K){
            sum=0;
            memset(sum_need,0,sizeof sum_need);
            memset(sum_offer,0,sizeof sum_offer);
            
            for(int i=1;i<=n;i++)
                for(int j=1;j<=K;j++){
                    scanf("%d",&need[i][j]);
                    sum_need[j]+=need[i][j];
                }
            for(int i=1;i<=m;i++)
                for(int j=1;j<=K;j++){
                    scanf("%d",&offer[i][j]);
                    sum_offer[j]+=offer[i][j];
                }
            int sign=0;
            for(int i=1;i<=K;i++)
                if(sum_offer[i]<sum_need[i]){
                    sign=1;
                    break;
                }
            s=0;
            t=n+m+1;
            for(int k=1;k<=K;k++){
                memset(mp,0,sizeof mp);
                memset(cost,0,sizeof cost);
                //第k件物品 供应商->店主的运费 
                for(int i=1+m;i<=n+m;i++)
                    for(int j=1;j<=m;j++){
                        scanf("%d",&cost[j][i]);
                        cost[i][j]-=cost[j][i];//反向边的费用 
                    }
                    
                if(sign==1)continue;
                
                for(int i=1;i<=m;i++)//s->供应商 
                    mp[s][i]=offer[i][k];
                for(int i=1;i<=m;i++)//供应商->店主 
                    for(int j=m+1;j<=m+n;j++)
                        mp[i][j]=offer[i][k];
                 for(int i=m+1;i<=m+n;i++)//店主->t 
                     mp[i][t]=need[i-m][k]; 
                sum+=fond(); 
            }
            if(sign==1)
                printf("-1
    ");
            else printf("%d
    ",sum);
        }
    }
  • 相关阅读:
    Codevs 1283 等差子序列
    Codevs 1282 约瑟夫问题
    Codevs 1228 苹果树
    Codevs 1191 数轴染色
    洛谷P1080 国王游戏
    Codevs 1523 地精部落
    2014-7-17 NOIP模拟赛
    Codevs 3409 搬运礼物
    Codevs 1425 最长公共子串
    TyvjP1863 [Poetize I]黑魔法师之门(2014-8-27)
  • 原文地址:https://www.cnblogs.com/zsben991126/p/11000716.html
Copyright © 2011-2022 走看看