Hdu--4780(费用流,上下界)

2015-02-23 16:11:16

思路:一道有上下界的费用流。

  建图:比较巧妙,根据题意思考,机器只会影响其第一个加工的糖果,而之后加工的糖果只与其之气加工的糖果有关,与机器无关。

  因此,我们建立一个超级源点,与各个机器连边,容量1费用0;同理再建立超级汇点,各个机器与超级汇点连边,这个很容易落掉

  (因为某些机器可以不用,所以直接流到超级汇点而不经过糖果。如果不建这条边,求最大流时,会使得某些不合算的机器也被用来加工糖果。)

  然后,因为每个糖果只有一颗,所以我们将糖果拆点,连边,容量1费用-INF(为了保证这颗糖果必须加工),再在机器与糖果之间建边,容量1,费用要通过时间来计算。

  最后,糖果之间建边,容量1,费用是转换费用。

  建完图后跑一遍最小费用最大流,然后将答案加上 n × INF(补偿回来),如果答案>INF,说明不是每颗糖果都加工过,输出-1。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <cmath>
  5 #include <vector>
  6 #include <map>
  7 #include <set>
  8 #include <stack>
  9 #include <queue>
 10 #include <string>
 11 #include <iostream>
 12 #include <algorithm>
 13 using namespace std;
 14 
 15 #define MEM(a,b) memset(a,b,sizeof(a))
 16 #define REP(i,n) for(int i=1;i<=(n);++i)
 17 #define REV(i,n) for(int i=(n);i>=1;--i)
 18 #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
 19 #define RFOR(i,a,b) for(int i=(a);i>=(b);--i)
 20 #define getmid(l,r) ((l) + ((r) - (l)) / 2)
 21 #define MP(a,b) make_pair(a,b)
 22 #define X first
 23 #define Y second
 24 
 25 typedef long long ll;
 26 typedef pair<int,int> pii;
 27 const ll INF = (1 << 28);
 28 const int MAXN = 510;
 29 
 30 int N,M,K;
 31 int C[MAXN][MAXN],D[MAXN][MAXN],E[MAXN][MAXN],F[MAXN][MAXN];
 32 int st[MAXN],ed[MAXN];
 33 
 34 struct edge{
 35     int v,next;
 36     ll cost;
 37     int cp;
 38 };
 39 
 40 inline int Read(){
 41     int x = 0;char ch = getchar();
 42     while(ch < '0' || ch > '9') ch = getchar();
 43     while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
 44     return x;
 45 }
 46 
 47 struct MCMF{
 48     edge e[MAXN * MAXN * 2];
 49     int sou,sin;
 50     int first[MAXN],ecnt;
 51     ll dis[MAXN];
 52     int prev[MAXN],pree[MAXN],inq[MAXN];
 53     void Init(){
 54         MEM(first,-1);
 55         ecnt = 0;
 56     }
 57     void Add_edge(int u,int v,int cap,int fee){
 58         e[++ecnt].next = first[u];
 59         e[ecnt].v = v;
 60         e[ecnt].cp = cap;
 61         e[ecnt].cost = fee;
 62         first[u] = ecnt;
 63 
 64         e[++ecnt].next = first[v];
 65         e[ecnt].v = u;
 66         e[ecnt].cp = 0;
 67         e[ecnt].cost = -fee;
 68         first[v] = ecnt;
 69     }
 70     bool Spfa(){
 71         fill(dis,dis + MAXN,INF);
 72         dis[sou] = 0;
 73         MEM(prev,-1),MEM(inq,0);
 74         queue<int> Q;
 75         while(!Q.empty()) Q.pop();
 76         Q.push(0);
 77         while(!Q.empty()){
 78             int x = Q.front(); Q.pop();
 79             inq[x] = 0;
 80             for(int i = first[x]; ~i; i = e[i].next){
 81                 if(e[i].cp <= 0) continue;
 82                 int v = e[i].v;
 83                 if(dis[x] + e[i].cost < dis[v]){
 84                     dis[v] = dis[x] + e[i].cost;
 85                     prev[v] = x;
 86                     pree[v] = i;
 87                     if(inq[v] == 0){
 88                         inq[v] = 1;
 89                         Q.push(v);
 90                     }
 91                 }
 92             }
 93         }
 94         return prev[sin] != -1;
 95     }
 96     ll Solve(){
 97         ll min_cost = 0;
 98         while(Spfa()){
 99             for(int i = sin; i != sou; i = prev[i]){
100                 int id = pree[i];
101                 e[id].cp--;
102                 e[((id - 1) ^ 1) + 1].cp++;
103             }
104             min_cost += dis[sin];
105         }
106         return min_cost;
107     }
108 }Nat;
109 
110 int main(){
111     while(scanf("%d%d%d",&N,&M,&K) != EOF,N + M + K){
112         Nat.Init();
113         REP(i,N) st[i] = Read(),ed[i] = Read();
114         REP(i,N) REP(j,M) C[i][j] = Read(); //init time
115         REP(i,N) REP(j,M) D[i][j] = Read(); //init cost
116         REP(i,N) REP(j,N) E[i][j] = Read(); //change time
117         REP(i,N) REP(j,N) F[i][j] = Read(); //change cost
118         Nat.sou = 0; //source : 0
119         //machine : 1 ~ M , candy(1) : M + 1 ~ M + N , candy(2) : M + N + 1 ~ M + 2 * N
120          Nat.sin = M + 2 * N + 1; //sin : M + 2 * N + 1
121         REP(i,M){
122             Nat.Add_edge(Nat.sou,i,1,0); //source - machines
123             Nat.Add_edge(i,Nat.sin,1,0); //machines - sink
124         }
125         REP(i,N){
126             Nat.Add_edge(M + i,M + N + i,1,-INF); //candy(1) - candy(2)
127             Nat.Add_edge(M + N + i,Nat.sin,1,0); //candy(2) - sink
128         }
129         REP(i,N) REP(j,M){    //candy(1)[i] , machine[j]
130             if(C[i][j] >= ed[i]) continue;
131             int add_cost = K * (max(C[i][j],st[i]) - st[i]);
132             Nat.Add_edge(j,M + i,1,D[i][j] + add_cost);
133         }
134         REP(i,N) REP(j,N) if(i != j){ //candy(2)[i] - candy(1)[j]
135             if(ed[i] + E[i][j] >= ed[j]) continue;
136             int add_cost = K * (max(ed[i] + E[i][j],st[j]) - st[j]);
137             Nat.Add_edge(M + N + i,M + j,1,F[i][j] + add_cost);
138         }
139         ll ans = Nat.Solve();
140         ans += N * INF;
141         if(ans >= INF) printf("-1\n");
142         else    printf("%d\n",ans);
143     }
144     return 0;
145 }

 

posted @ 2015-02-23 16:23  Naturain  阅读(197)  评论(0编辑  收藏  举报