程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> POJ 2516 Minimum Cost 費用流

POJ 2516 Minimum Cost 費用流

編輯:C++入門知識

題意:有M個貨物供應點,它提供k種貨物,有N個商店,這N個商店分別要從貨物點訂購一定量的這k種物品,每個供應點對這k種貨物的供應量不同,每個商店對k種物品的需求量也不同,每個貨物供應點向每個商店送不同種貨物的單個物品的花費不同,現在給出貨物供應點、商店、k種貨物、花費間的關系,現在讓你針對商店給出的訂單,讓你決定如何使所有供應點完成訂單任務的最小花費,若能完成任務,則輸出最小花費,否則輸出-1.
為我的英語拙計啊。。。到網上找了翻譯才看懂。。太水了。
第一次寫費用流,參考了別人的代碼,寫了點注釋,算是費用流第一A。紀念一下。。
貼代碼
[cpp]
#include <iostream> 
#include <cstdio> 
#include <algorithm> 
#include <string> 
#include <cmath> 
#include <cstring> 
#include <queue> 
#include <set> 
#include <vector> 
#include <stack> 
#include <map> 
#include <iomanip> 
#define PI acos(-1.0) 
#define Max 105 
#define inf 1<<28 
#define LL(x) (x<<1) 
#define RR(x) (x<<1|1) 
using namespace std; 
 
int c[Max][Max]; //流量限制 
int f[Max][Max];//最大流 
int dis[Max]; 
int w[Max][Max];//費用 
bool visit[Max]; 
int path[Max]; 
int S,T; 
int q[Max*100]; 
int spfa()//最短路 

    int i,j; 
    for(i=0; i<=T; i++) 
        dis[i]=inf,path[i]=-1,visit[i]=0; 
    dis[S]=0; 
    visit[S]=1; 
    int num=0,cnt=0; 
    q[num++]=S; 
    while(num>cnt) 
    { 
        int temp=q[cnt++]; 
        visit[temp]=0; 
        for(i=1; i<=T; i++) 
            if(c[temp][i]>f[temp][i]&&dis[temp]+w[temp][i]<dis[i]) 
            { 
                path[i]=temp; 
                dis[i]=dis[temp]+w[temp][i]; 
                if(!visit[i]) 
                { 
                    visit[i]=1; 
                    q[num++]=i; 
                } 
            } 
    } 
    if(path[T]==-1) 
    return 0; 
    return 1; 

void getMaxflow()//找增廣路並調整流量 

    while(spfa()) 
    { 
        int maxFlow=inf; 
        int pre=T; 
        while(path[pre]!=-1) 
        { 
            maxFlow=min(maxFlow,c[path[pre]][pre]-f[path[pre]][pre]); 
            pre=path[pre]; 
        } 
        pre=T; 
        while(path[pre]!=-1)//調整流量 
        { 
            f[path[pre]][pre]+=maxFlow; 
            f[pre][path[pre]]=-f[path[pre]][pre]; 
            pre=path[pre]; 
        } 
    } 

int need[Max][Max],have[Max][Max]; 
int cost[Max][Max][Max]; 
int main() 

    int i,j,k,l,n,m,d; 
 
    while(scanf("%d%d%d",&n,&m,&k),(n+m+k)) 
    { 
        for(i=1; i<=n; i++) //客人i 
            for(j=1; j<=k; j++) //需要貨物j的數量 
                scanf("%d",&need[i][j]); 
        for(i=1; i<=m; i++) //倉庫i 
            for(j=1; j<=k; j++) //有貨物j的數量 
                scanf("%d",&have[i][j]); 
        for(i=1; i<=k; i++) //第i個商品 
            for(j=1; j<=n; j++) //送到j地點 
                for(d=1; d<=m; d++) //從d地點的 
                    scanf("%d",&cost[i][d][j]);//的費用 
        S=0,T=n+m+1;//超級源點0,超級匯點n+m+1; 
        //cout<<1<<endl; 
        bool flag=0; 
        int ans=0; 
        for(i=1; i<=k; i++) 
        { 
            memset(c,0,sizeof(c)); 
            memset(f,0,sizeof(f)); 
            memset(w,0,sizeof(w)); 
            for(j=1; j<=m; j++)//源點到每個倉庫的容量為該倉庫這種物品的存量 
                c[0][j]=have[j][i]; 
            for(j=1; j<=n; j++)//每個客人到匯點的容量為該客人對物品的需求量 
                c[m+j][T]=need[j][i]; 
            for(j=1; j<=m; j++) 
                for(d=1; d<=n; d++) 
                    c[j][d+m]=have[j][i];//每個倉庫到每個客人之間的容量為該倉庫這種物品的存量 
            for(j=1; j<=m; j++) 
                for(d=1; d<=n; d++) 
                    w[j][d+m]=cost[i][j][d],w[d+m][j]=-w[j][d+m];//花費,負花費用於回流 
            getMaxflow(); 
            //cout<<1<<endl; 
            for(j=1; j<=n; j++) 
                if(c[j+m][T]!=f[j+m][T])//如果不能供貨,則輸出-1 
                { 
                    flag=1; 
                    break; 
                } 
            if(flag) 
                break; 
            for(j=1; j<=m; j++) 
                for(d=1; d<=n; d++) 
                    ans+=f[j][d+m]*w[j][d+m];//總費用 
                   // cout<<1<<endl; 
        } 
        if(flag) 
            cout<<"-1"<<endl; 
        else 
            cout<<ans<<endl; 
    } 
    return 0; 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved