hdu 4780区域赛 (费用流)

来源:互联网 发布:品牌 用户画像 大数据 编辑:程序博客网 时间:2024/05/22 17:32
  A new candy factory opens in pku-town. The factory import M machines to produce high quality candies. These machines are numbered from 1 to M. 
  There are N candies need to be produced. These candies are also numbered from 1 to N. For each candy i , it can be produced in any machine j. It also has a producing time(s i,t i) , meaning that candy i must start producing at time s i and will finish at t i. Otherwise if the start time is p i(s i < p i < t i) then candy will still finish at t i but need additional K*(p i - s i) cost. The candy can’t be produced if p i is greater than or equal to t i. Of course one machine can only produce at most one candy at a time and can’t stop once start producing. 
  On the other hand, at time 0 all the machines are in their initial state and need to be “set up” or changed before starting producing. To set up Machine j from its initial state to the state which is suitable for producing candiy i, the time required is C ij and cost is D ij. To change a machine from the state suitable for candy i 1 into the state suitable for candy i 2, time required is E i1i2 and cost is F i1i2
  As the manager of the factory you have to make a plan to produce all the N candies. While the sum of producing cost should be minimized. 
 

Input

  There are multiple test cases. 
  For each case, the first line contains three integers N(1<=N<=100), M(1<=M<=100), K(1<=K<=100) . The meaning is described above. 
  Then N lines follow, each line contains 2 integers s i and t i(0 <= s i < t i <100000). 
  Then N lines follow, each line contains M integers, the j-th integer of the i-th line indicating C ij(1<=C ij<=100000) . 
  Then N lines follow, each line contains M integers, the j-th integer of the i-th line indicating D ij(1<=D ij<=100000) . 
  Then N lines follow, each line contains N integers, the i 2-th integer of the i 1-th line indicating E i1i2(1<=E i1j2<=100000) . 
  Then N lines follow, each line contains N integers, the i 2-th integer of the i 1-th line indicating F i1i2(1 <= F i1j2<=100000) . 
  Since the same candy will only be produced once, E ii and F ii are meaningless and will always be -1. 
  The input ends by N=0 M=0 K=0. Cases are separated with a blank line.
 

Output

  For each test case, if all of M candies can be produced, output the sum of minimum producing cost in a single line. Otherwise output -1. 
 

Sample Input

3 2 14 72 48 94 43 33 32 812 314 6-1 1 11 -1 11 1 -1-1 5 55 -1 55 5 -11 1 21 555-1-10 0 0
 

Sample Output

11-1
题意 : 有M台机器, 要生产n个糖果; 每个糖果可以随意用哪个机器来生产。 糖果有生产的开始和结束时间time_s,time_t; 当生产时间为Pt (time_s < pt < time_t) , 如果还要坚持生产该糖果, 则需要支付
k*(Pt-time_s)的费用 ; 刚开始机器都是初始状态,使用j机器生产i糖果需要把j机器从初始状态设置为可以生产i糖果的状态,设置状态需要花费时间Cij和费用Dij ; 把机器从生产i1糖果状态设置为生产i2糖果状态,也需要花费时间Ei1i2和费用Fi1i2 ; 问生产n个糖果需要的最小费用,如果不能生产完n个 ,输出-1 ;
分析 : 糖果拆点, 源点连n个糖果,add(s,i,1,0) ,控制流进的流量就是n;
n个糖果对初始状态的机器设置后能用来生产的机器连边;接着M个机器连汇点,add(i+n,t,1,0);
再考虑,机器在糖果状态之间转换设置时 ;
拆点后,n个糖果中 如果糖果i1状态设置为i2状态后,能够用来生产糖果i2,则连边
add(i1,i2,1,费用) ;
#include<cstdio>#include<cstring>#include<map>#include<vector>#include<cmath>#include<cstdlib>#include<stack>#include<queue>#include <iomanip>#include<iostream>#include<algorithm>using namespace std ;const int N=1000;const int M=1000010;const int inf=1<<30 ;struct node{int u ,v,c,cost,next;}edge[M];int head[N],dis[N],pre[N],vist[N],pp[N],inq[N];int top , flow ;const int MAXN = 110;int n, m, k;int candy_s[MAXN], candy_t[MAXN];int start_time[MAXN][MAXN], start_cost[MAXN][MAXN];int change_time[MAXN][MAXN], change_cost[MAXN][MAXN];queue<int>q;void add(int u ,int v , int c,int cost){  edge[top].u=u;  edge[top].v=v;  edge[top].c=c;  edge[top].cost=cost;  edge[top].next=head[u];  head[u]=top++;  edge[top].u=v;  edge[top].v=u;  edge[top].c=0;  edge[top].cost=-cost;  edge[top].next=head[v];  head[v]=top++;}int SPFA(int s,int t){    memset(pre, -1, sizeof(pre));        memset(vist, 0, sizeof(vist));        for(int i = 0 ; i <= t ; i++)  dis[i]=inf;        dis[s] = 0;vist[s]=1;pre[s]=s;        q.push(s);        while (!q.empty()) {            int u = q.front(); q.pop();            vist[u] = 0;            for (int i = head[u]; i != -1; i = edge[i].next) {                int v = edge[i].v;                if (edge[i].c > 0 && dis[v] > dis[u] + edge[i].cost) {                    dis[v] = dis[u] + edge[i].cost;                    pre[v] = u; pp[v] = i;                    if (!vist[v]) { vist[v] = 1; q.push(v); }                }            }        }        if (pre[t] == -1) return 0;        else return 1 ;}int  MCMF(int s, int t) {    int mincost = 0;     flow = 0;    while (SPFA(s,t)) {               int minflow = inf;        for (int i = t; i != s; i = pre[i])            minflow = min(minflow, edge[pp[i]].c);        for (int i = t; i != s; i = pre[i]) {            edge[pp[i]].c -= minflow;            edge[pp[i] ^ 1].c += minflow;        }        flow += minflow;        mincost += dis[t] * minflow;    }    return mincost;}int main(){  while(~scanf("%d%d%d",&n,&m,&k))  {      if((n+m+k)==0) break;for(int i =  0 ; i < n ; i++)    scanf("%d%d",&candy_s[i],&candy_t[i]) ;    for(int i = 0 ; i < n ; i++)  for(int j = 0 ; j < m ; j++)    scanf("%d",&start_time[i][j]);for(int i = 0 ; i < n ; i++)  for(int j = 0 ; j < m ; j++)    scanf("%d",&start_cost[i][j]);            for(int i = 0 ; i < n ; i++)  for(int j = 0 ; j < n ; j++)    scanf("%d",&change_time[i][j]);for(int i = 0 ; i < n ; i++)  for(int j = 0 ; j < n ; j++)    scanf("%d",&change_cost[i][j]);    top=0;memset(head,-1,sizeof(head));int s=2*n+m,t=s+1;for(int i = 0 ; i < n ; i++)    add(s,i,1,0);    for(int i = 0 ; i < m ; i++)    add(i+n,t,1,0);    for(int i = 0 ; i < n ; i++)    add(i+n+m,t,1,0);   for (int i = 0; i < n; i++)   //机器从初始状态的转换            for (int j = 0; j < m; j++)    {             if (start_time[i][j] >= candy_t[i]) continue;             int cost = start_cost[i][j];             if (start_time[i][j] > candy_s[i])                cost += k * (start_time[i][j] - candy_s[i]);                add(i, j + n, 1, cost);           }       for (int i = 0; i < n; i++)    //糖果状态之间的转换           for (int j = 0; j < n; j++)     if (i != j)     {             int dt = candy_t[i] + change_time[i][j];             if (dt >= candy_t[j]) continue;             int cost = change_cost[i][j];             dt -= candy_s[j];             if (dt > 0)                cost += k * dt;               add(j, i + n + m, 1, cost);           }          int ans = MCMF(s, t);         if (flow < n) puts("-1");         else printf("%d\n", ans);  }  return 0 ;}


0 0