POJ 2516 Minimum Cost (最小費用最大流,KM解法)

來源:互聯網
上載者:User

題意:有N個客戶,M個倉庫,和K種貨物。已知每個客戶需要每種貨物的數量,每個倉庫儲存每種貨物的數量,每個倉庫運輸各種貨物去各個客戶的單位費用。判斷所有的倉庫能否滿足所有客戶的需求,如果可以,求出最少的運輸總費用。

題解:因為 K 種產品互相不干擾,所以關鍵是把 K 種產品分開求解。給出了兩種slack方式。

#include <iostream>using namespace std;#define N 155#define INF 999999int need[N][N], store[N][N], cost[N][N][N];int A[N], B[N], visA[N], visB[N];int match[N], fee[N][N], slack;int n, m, kind, X, Y;bool find_path ( int i ){visA[i] = 1;for ( int j = 1; j <= Y; j++ ){if ( visB[j] ) continue;int temp = fee[i][j] - (A[i] + B[j]);if ( temp == 0 ){visB[j] = 1;if ( ! match[j] || find_path(match[j]) ){match[j] = i;return true;}}else if ( slack > temp )slack = temp;}return false;}void KM(){int i, j;memset(B,0,sizeof(B));memset(match,0,sizeof(match));for ( i = 1; i <= X; i++ ){A[i] = INF;for ( j = 1; j <= Y; j++ )if ( A[i] > fee[i][j] )A[i] = fee[i][j];}for ( i = 1; i <= X; i++ ){while ( 1 ){slack = INF;memset(visA,0,sizeof(visA));memset(visB,0,sizeof(visB));if ( find_path ( i ) ) break;/*注意!:A中位於交錯樹中的點加上slack,B中位於交錯樹中的點減去slack,若反過來則TLE*/for ( j = 1; j <= X; j++ )if ( visA[j] ) A[j] += slack;for ( j = 1; j <= Y; j++ )if ( visB[j] ) B[j] -= slack;}}}int solve(){int i, j, k, ans = 0;for ( k = 1; k <= kind; k++ ){X = Y = 0;for ( i = 1; i <= n; i++ )for ( j = 1; j <= need[i][k]; j++ )A[++X] = i;for ( i = 1; i <= m; i++ )for ( j = 1; j <= store[i][k]; j++ )B[++Y] = i;memset(fee,0,sizeof(fee));for ( i = 1; i <= X; i++ )for ( j = 1; j <= Y; j++ )fee[i][j] = cost[k][A[i]][B[j]];KM();for ( i = 1; i <= Y; i++ )ans += fee[match[i]][i];}return ans;}int main(){while ( scanf("%d%d%d",&n,&m,&kind) ){if ( !n && !m && !kind ) break;int i, j, k;for ( i = 1; i <= n; i++ )for ( j = 1; j <= kind; j++ )scanf("%d",&need[i][j]);for ( i = 1; i <= m; i++ )for ( j = 1; j <= kind; j++ )scanf("%d",&store[i][j]);for ( k = 1; k <= kind; k++ )for ( i = 1; i <= n; i++ )for ( j = 1; j <= m; j++ )scanf("%d",&cost[k][i][j]);for ( k = 1; k <= kind; k++ ){int totalNeed = 0;int totalStore = 0;for ( i = 1; i <= n; i++ )totalNeed += need[i][k];for ( i = 1; i <= m; i++ )totalStore += store[i][k];if ( totalStore < totalNeed ){printf("-1\n");goto next;}}printf("%d\n",solve());next:;}return 0;}

 

 

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define N 155#define INF 999999int need[N][N], store[N][N], cost[N][N][N];int A[N], B[N], visA[N], visB[N];int match[N], fee[N][N], slack[N];int n, m, kind, X, Y;bool find_path ( int i ){visA[i] = 1;for ( int j = 1; j <= Y; j++ ){if ( visB[j] ) continue;if ( fee[i][j] == A[i] + B[j] ){visB[j] = 1;if ( -1 == match[j] || find_path(match[j]) ){match[j] = i;return true;}}else if ( slack[j] > A[i] + B[j] - fee[i][j] )slack[j] = A[i] + B[j] - fee[i][j];}return false;}void KM(){int i, j, d;memset(B,0,sizeof(B));memset(match,-1,sizeof(match));for ( i = 1; i <= X; i++ )for (A[i] = -INF, j = 1; j <= Y; j++ )            if ( A[i] < fee[i][j] )                A[i] = fee[i][j];for ( i = 1; i <= X; i++ ){    for ( j = 1; j <= Y; j++ )            slack[j] = INF;while ( 1 ){memset(visA,0,sizeof(visA));memset(visB,0,sizeof(visB));if ( find_path ( i ) ) break;            for ( d = INF, j = 1; j <= Y; j++ )                if ( !visB[j] && d > slack[j] ) d = slack[j];for ( j = 1; j <= X; j++ )if ( visA[j] ) A[j] -= d;for ( j = 1; j <= Y; j++ )if ( visB[j] ) B[j] += d;                else slack[j] -= d;}}}int solve(){int i, j, k, ans = 0;for ( k = 1; k <= kind; k++ ){X = Y = 0;for ( i = 1; i <= n; i++ )for ( j = 1; j <= need[i][k]; j++ )A[++X] = i;for ( i = 1; i <= m; i++ )for ( j = 1; j <= store[i][k]; j++ )B[++Y] = i;memset(fee,0,sizeof(fee));for ( i = 1; i <= X; i++ )for ( j = 1; j <= Y; j++ )fee[i][j] = -cost[k][A[i]][B[j]];KM();for ( i = 1; i <= Y; i++ )            if ( match[i] != -1 ) //注意,match[i]必須在已經匹配的情況下才能相加    ans += fee[match[i]][i];}return -ans;}int main(){while ( scanf("%d%d%d",&n,&m,&kind) ){if ( !n && !m && !kind ) break;int i, j, k;for ( i = 1; i <= n; i++ )for ( j = 1; j <= kind; j++ )scanf("%d",&need[i][j]);for ( i = 1; i <= m; i++ )for ( j = 1; j <= kind; j++ )scanf("%d",&store[i][j]);for ( k = 1; k <= kind; k++ )for ( i = 1; i <= n; i++ )for ( j = 1; j <= m; j++ )scanf("%d",&cost[k][i][j]);for ( k = 1; k <= kind; k++ ){int totalNeed = 0;int totalStore = 0;for ( i = 1; i <= n; i++ )totalNeed += need[i][k];for ( i = 1; i <= m; i++ )totalStore += store[i][k];if ( totalStore < totalNeed ){printf("-1\n");goto next;}}printf("%d\n",solve());next:;}return 0;}

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.