hdu 4780区域赛 (费用流)

  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 1 4 7 2 4 8 9 4 4 3 3 3 3 2 8 12 3 14 6 -1 1 1 1 -1 1 1 1 -1 -1 5 5 5 -1 5 5 5 -1 1 1 2 1 5 5 5 -1 -1 0 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值