FZU2143Board Game(最小费用流)

题目大意是说有一个B矩阵,现在A是一个空矩阵(每个元素都为0),每次操作可以将A矩阵相邻的两个元素同时+1,但是有个要求就是A矩阵的每个元素都不可以超过K,求

这个的最小值

 

解题思路是这样的,新建起点与奇点(i != j)连K条边,第i条边的权值为(i - B)^2 - (i - 1 - B)^2 = 2 * i - 1 - 2 * B(这样可以保证如果此边的流量为a, 花费始终是(a-b)^2);另外新建终点与偶点相连,代价与上诉一致;

然后跑一遍最小费用流,知道cost>=0时为止。祥见代码:

  1 #include <map>
  2 #include <set>
  3 #include <stack>
  4 #include <queue>
  5 #include <cmath>
  6 #include <ctime>
  7 #include <vector>
  8 #include <cstdio>
  9 #include <cctype>
 10 #include <cstring>
 11 #include <cstdlib>
 12 #include <iostream>
 13 #include <algorithm>
 14 using namespace std;
 15 #define INF 0x3f3f3f3f
 16 #define inf (-((LL)1<<40))
 17 #define lson k<<1, L, mid
 18 #define rson k<<1|1, mid+1, R
 19 #define mem0(a) memset(a,0,sizeof(a))
 20 #define mem1(a) memset(a,-1,sizeof(a))
 21 #define mem(a, b) memset(a, b, sizeof(a))
 22 #define FIN freopen("in.txt", "r", stdin)
 23 #define FOUT freopen("out.txt", "w", stdout)
 24 #define rep(i, a, b) for(int i = a; i <= b; i ++)
 25 
 26 template<class T> T CMP_MIN(T a, T b) { return a < b; }
 27 template<class T> T CMP_MAX(T a, T b) { return a > b; }
 28 template<class T> T MAX(T a, T b) { return a > b ? a : b; }
 29 template<class T> T MIN(T a, T b) { return a < b ? a : b; }
 30 template<class T> T GCD(T a, T b) { return b ? GCD(b, a%b) : a; }
 31 template<class T> T LCM(T a, T b) { return a / GCD(a,b) * b;    }
 32 
 33 //typedef __int64 LL;
 34 typedef long long LL;
 35 const int MAXN = 10010;
 36 const int MAXM = 20010;
 37 const double eps = 1e-4;
 38 
 39 
 40 const int dx[4] = {0, 1, 0, -1};
 41 const int dy[4] = {1, 0, -1, 0};
 42 int T, N, M, K, B, ans = 0;
 43 
 44 /*******************************************************************/
 45 struct Edge {
 46     int to, cap, flow, cost, next;
 47     Edge(){}
 48     Edge(int _n, int _v, int _c, int _f, int _cost){
 49         next = _n; to = _v; cap = _c;
 50         flow = _f; cost = _cost;
 51     }
 52 };
 53 
 54 struct MCMF
 55 {
 56     int n, m, src, des;
 57     int head[MAXN], tot;
 58     Edge edges[MAXM];
 59     int inq[MAXN];
 60     int d[MAXN];
 61     int p[MAXN];
 62     int a[MAXN];
 63 
 64     void init(int n) {
 65         this->tot = 0;
 66         this->n = n;
 67         mem1(head);
 68     }
 69 
 70     void add_edge(int from, int to, int cap, int cost) {
 71         edges[tot] = Edge(head[from], to, cap, 0, cost);
 72         head[from] = tot ++;
 73         edges[tot] = Edge(head[to], from, 0, 0, -cost);
 74         head[to] = tot ++;
 75     }
 76 
 77     bool bellman_ford(int s, int t, int& flow) {
 78         for(int i = 0; i < n; i ++) {
 79             d[i] = INF;
 80             inq[i] = 0;
 81         }
 82         d[s] = 0; inq[s] = 1;
 83         p[s] = 0; a[s] = INF;
 84 
 85         queue<int>Q;
 86         Q.push(s);
 87         while(!Q.empty()) {
 88             int u = Q.front(); Q.pop();
 89             inq[u] = false;
 90             for(int i = head[u]; i != -1; i = edges[i].next) {
 91                 int v = edges[i].to;
 92                 if(edges[i].cap > edges[i].flow && d[v] > d[u] + edges[i].cost) {
 93                     d[v] = d[u] + edges[i].cost;
 94                     p[v] = i;
 95                     a[v] = min(a[u], edges[i].cap - edges[i].flow);
 96                     if(!inq[v]) {
 97                         Q.push(v);
 98                         inq[v] = 1;
 99                     }
100                 }
101             }
102         }
103         if(d[t] >= 0) return false;
104 
105         flow += a[t];
106         ans += d[t] * a[t];
107 
108         int u = t;
109         while(u != s) {
110             edges[p[u]].flow += a[t];
111             edges[p[u]^1].flow -= a[t];
112             u = edges[p[u]^1].to;
113         }
114         return true;
115     }
116 
117     int min_cost(int s, int t) {
118         int flow = 0;
119         while(bellman_ford(s, t, flow));
120         return ans;
121     }
122 
123 };
124 /***************************************************************/
125 
126 int idx(int i, int j) {
127     return (i - 1) * M + j;
128 }
129 
130 int ok(int i, int j) {
131     return (i >= 1 && i <= N && j >= 1 && j <= M);
132 }
133 
134 
135 MCMF mcmf;
136 
137 int main()
138 {
139     //FIN;
140     cin >> T;
141     rep (t, 1, T) {
142         scanf("%d %d %d", &N, &M, &K);
143         mcmf.init(N * M + 2);
144         mcmf.src = 0; mcmf.des = N * M + 1; ans = 0;
145         rep (i, 1, N) rep (j, 1, M) {
146             scanf("%d", &B);
147             ans += B * B;
148             if(i % 2 == j % 2) rep (k, 1, K) {
149                 mcmf.add_edge(mcmf.src, idx(i, j), 1, 2 * k - 1 - 2 * B);
150                 rep (k, 0, 3) if(ok(i + dx[k], j + dy[k])) {
151                     mcmf.add_edge(idx(i, j), idx(i + dx[k], j + dy[k]), INF, 0);
152                 }
153             }
154             else rep (k, 1, K) {
155                 mcmf.add_edge(idx(i, j), mcmf.des, 1, 2 * k - 1 - 2 * B);
156             }
157         }
158         printf("Case %d: %d\n", t, mcmf.min_cost(mcmf.src, mcmf.des));
159     }
160     return 0;
161 }

 

posted @ 2015-03-28 22:27  再见~雨泉  阅读(346)  评论(0编辑  收藏  举报