標籤:style http color os io strong for 資料
題目連結:http://poj.org/problem?id=2516
題意:有N個店,M個供貨商,K種商品。已知供貨商的倉庫裡每種商品的數量以及每種商品運送到每個店的費用,每個店鋪對各種商品的需求數量,求最少話費。
Input
第一行:N,M,K。
然後1 - N行,每行 K列 ,第I行第J個數代表 第I個店鋪 需要第J種物品多少件。
然後 N+1 - M行 ,每行 K列 , 第I行第J個數代表 第I個供貨商 有第J種物品多少件。
然後是K個矩陣 ,每個N行M列,第ji個矩陣的第i行第j列代表著第j個供貨商給第i個店鋪發第ji種貨物一件需要的費用。哎喲,我日
坑題一道啊,感覺已經不是在考查網路流,而是在考察對 繁瑣資料輸入 的Debug能力,弄了一上午,坑我啊。。。
思路:一開始思路就是錯的,上去就拆點,將供貨商和店鋪對應著K種商品,把每個供貨商拆成K個,店鋪拆成K個,寫了一半感覺不對勁,50*50 + 50*50 + 50,肯定逾時。
既然拆點不行,那麼就拆網唄。。。把對應所有商品的整個網路,拆成K個單種商品的網路,求出單個商品的最小費用,最後進行累加即可
建圖:
增設兩個點,源點s = 0,匯點t = N+M+1,源點與供貨商相連,費用0,容量為當前單種商品的供給量
供貨商與店鋪相連費用已知,容量為正無窮。
店鋪與匯點相連,費用0,容量為當前單種商品的需求。
#include <iostream>#include <cstdlib>#include <cstdio>#include <cstring>#include <queue>#include <algorithm>const int maxn = 110;const int maxm = 10000;const int inf = 1e8;#define MIN INT_MIN#define MAX 1e6#define LL long long#define init(a) memset(a,0,sizeof(a))#define FOR(i,a,b) for(int i = a;i<b;i++)#define max(a,b) (a>b)?(a):(b)#define min(a,b) (a>b)?(b):(a)using namespace std;struct node{ int u,v,w,cap,next;}edge[maxm];int pre[maxn],dis[maxn],head[maxn],cnt;bool vis[maxn];int n,m;void add(int u,int v,int c,int cap){ edge[cnt].u=u; edge[cnt].v=v; edge[cnt].w=c; edge[cnt].cap=cap; edge[cnt].next=head[u]; head[u]=cnt++; edge[cnt].u=v; edge[cnt].v=u; edge[cnt].w=-c; edge[cnt].cap=0; edge[cnt].next=head[v]; head[v]=cnt++;}int spfa(int s,int t){ queue<int>q; while(q.empty()==false) q.pop(); q.push(s); memset(vis,0,sizeof(vis)); memset(pre,-1,sizeof(pre)); FOR(i,s,t+1) dis[i] = inf; dis[s]=0; while(!q.empty()) { int u=q.front(); q.pop(); vis[u] = 0; for(int i=head[u];i!=-1;i=edge[i].next) { if(edge[i].cap && dis[edge[i].v]>dis[u]+edge[i].w) { dis[edge[i].v]=dis[u]+edge[i].w; pre[edge[i].v] = i; if(!vis[edge[i].v]) { vis[edge[i].v]=1; q.push(edge[i].v); } } } } if(dis[t] != inf) return 1; else return 0;}int MinCostMaxFlow(int s,int t){int flow=0,cost=0; while(spfa(s,t)) {int df = inf;for(int i = pre[t];i!=-1;i=pre[edge[i].u]){if(edge[i].cap<df)df = edge[i].cap;}flow += df; for(int i=pre[t];i!=-1;i=pre[edge[i].u]) { edge[i].cap -= df; edge[i^1].cap += df; }cost += dis[t] * df; } return cost;}void initt(){ cnt=0; memset(head,-1,sizeof(head));}int main(){ int gong[51],qiu[51]; int k,s,t; int need[200][200],gei[200][200]; while(scanf("%d%d%d",&n,&m,&k),n,m,k) { init(need);init(gei); init(gong);init(qiu); s = 0,t = n+m+1; FOR(i,1,n+1) { FOR(j,1,k+1) { scanf("%d",&need[i][j]); qiu[j] += need[i][j]; } } FOR(i,1,m+1) { FOR(j,1,k+1) { scanf("%d",&gei[i][j]); gong[j] += gei[i][j]; } } bool flag = 1; FOR(i,1,k+1) { if(gong[i]<qiu[i])//如果單種商品的供給量不滿足該商品的需求量,直接列印-1 { flag = 0; break; } } int cost,yao,money = 0; FOR(ji,1,k+1) { initt(); FOR(i,1,n+1) { FOR(j,1,m+1) { scanf("%d",&cost); if(flag==0) continue; add(j,m+i,cost,inf);//供給商和店主的流量為正無窮 } } if(flag==0) continue; FOR(i,1,n+1) { add(m+i,t,0,need[i][ji]);//店鋪和匯點的費用為0,流量為店對該種商品的需求 } FOR(i,1,m+1) { add(s,i,0,gei[i][ji]);//源點對供應商的費用為0,流量為供貨商對該種商品的供給 } money += MinCostMaxFlow(s,t); } (flag==0)?puts("-1"):printf("%d\n",money); } return 0;}