POJ 2516 최소 비용 최소 비용 흐름

4910 단어 poj
제목: 
n * kk 의 행렬 을 보 여 줍 니 다. 격자 a [i] [k] 는 첫 번 째 고객 이 k 번 째 화물 a [i] [k] 단 위 를 필요 로 한 다 는 것 을 표시 합 니 다.
m * kk 의 행렬 을 보 여 줍 니 다. 격자 b [j] [k] 는 j 번 째 공급 업 체 가 k 번 째 화물 b [j] [k] 단 위 를 제공 할 수 있 음 을 표시 합 니 다.
k 개 n * m 의 행렬 을 제시 합 니 다. 격자 c [k] [i] [j] 는 제 k 종 화물 을 j 공급 업 체 가 고객 i 에 게 제공 하면 단위 당 운임 은 c [k] [i] [j] 라 고 합 니 다.
최소 비용 을 묻다.
 
분석:
처음에는 모든 화물 이 사실 상관 이 없다 는 것 을 고려 했 지만 비용 흐름 을 달 릴 때 큰 영향 을 미 치지 않 을 것 이 라 고 생각 하여 직접 그림 을 만들어 최소 비용 흐름, TLE 를 달 렸 다.
그 후에 모든 화물 에 대해 단독으로 고려 했다. 즉, 그림 을 만 든 후에 최소 비용 흐름 을 한 번 뛰 고 k 번 비용 흐름 을 구 한 후에 총 흐름 이 수요 하 는 화물 수량 과 같 는 지 판단 했다.이렇게 그림 을 만 들 면 노드 수가 현저히 줄 어 들 고 실제 효과 가 매우 뚜렷 하 다.
 
 
#include <set>

#include <map>

#include <list>

#include <cmath>

#include <queue>

#include <stack>

#include <string>

#include <vector>

#include <cstdio>

#include <cstring>

#include <iostream>

#include <algorithm>



using namespace std;



typedef long long ll;

typedef unsigned long long ull;



#define debug puts("here")

#define rep(i,n) for(int i=0;i<n;i++)

#define rep1(i,n) for(int i=1;i<=n;i++)

#define REP(i,a,b) for(int i=a;i<=b;i++)

#define foreach(i,vec) for(unsigned i=0;i<vec.size();i++)

#define pb push_back

#define RD(n) scanf("%d",&n)

#define RD2(x,y) scanf("%d%d",&x,&y)

#define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)

#define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w)

#define All(vec) vec.begin(),vec.end()

#define MP make_pair

#define PII pair<int,int>

#define PQ priority_queue

#define cmax(x,y) x = max(x,y)

#define cmin(x,y) x = min(x,y)

#define Clear(x) memset(x,0,sizeof(x))

/*



#pragma comment(linker, "/STACK:1024000000,1024000000")



int size = 256 << 20; // 256MB

char *p = (char*)malloc(size) + size;

__asm__("movl %0, %%esp
" :: "r"(p) ); */ char IN; inline void Int(int &x){ while(!isdigit(IN=getchar())); x = IN-'0'; while(isdigit(IN=getchar())) x = x*10+IN-'0'; } /******** program ********************/ const int MAXN = 205; const int MAXM = 100005; const int INF = 1e9; const int X = 52; int pre[MAXN],dis[MAXN]; int po[MAXN],tol; bool use[MAXN]; int q[MAXM],head,tail; int n,m,vs,vt,ans; int a[X][X],b[X][X],c[X][X][X]; int kk,flow; struct node{ int y,f,cost,next; }edge[MAXM]; void Add(int x,int y,int f,int cost){ edge[++tol].y = y; edge[tol].f = f; edge[tol].cost = cost; edge[tol].next = po[x]; po[x] = tol; } void add(int x,int y,int f,int cost){ Add(x,y,f,cost); Add(y,x,0,-cost); } bool spfa(){ memset(use,false,sizeof(use)); rep1(i,vt) dis[i] = INF; dis[vs] = 0; head = tail = 0; q[tail++] = vs; pre[vs] = 0; while(head<tail){ int x = q[head++]; use[x] = false; for(int i=po[x];i;i=edge[i].next){ int y = edge[i].y; if(edge[i].f>0&&edge[i].cost+dis[x]<dis[y]){ dis[y] = dis[x]+edge[i].cost; pre[y] = i; if(!use[y]){ use[y] = true; q[tail++] = y; } } } } if(dis[vt]==INF) return false; int aug = INF; for(int i=pre[vt];i;i=pre[edge[i^1].y]) aug = min(aug,edge[i].f); for(int i=pre[vt];i;i=pre[edge[i^1].y]){ edge[i].f -= aug; edge[i^1].f += aug; } ans += dis[vt]*aug; return true; } inline void fareFlow(int k){ Clear(po); tol = 1; vs = MAXN-3; vt = vs+1; rep1(i,n)if(a[i][k]) add( vs,i,a[i][k],0 ); rep1(j,m)if(b[j][k]){ add( j+n,vt,b[j][k],0 ); rep1(i,n) add(i,j+n,b[j][k],c[k][i][j]); } while(spfa()) ; for(int i=po[vt];i;i=edge[i].next) if(edge[i].f>0) flow += edge[i].f; } int main(){ #ifndef ONLINE_JUDGE freopen("sum.in","r",stdin); //freopen("sum.out","w",stdout); #endif while(true){ Int(n);Int(m);Int(kk); if(!n&&!m&&!kk)return 0; int tot = 0; rep1(i,n) rep1(k,kk){ Int(a[i][k]); tot += a[i][k]; } rep1(j,m) rep1(k,kk) Int(b[j][k]); rep1(k,kk) rep1(i,n) rep1(j,m) Int(c[k][i][j]); flow = 0; ans = 0; rep1(k,kk) fareFlow(k); printf("%d
",tot==flow?ans:-1); } return 0; }

 
  
 

좋은 웹페이지 즐겨찾기