【BZOJ3894】 文理分科

Description

 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠
结过)
 小P所在的班级要进行文理分科。他的班级可以用一个n*m的矩阵进行
描述,每个格子代表一个同学的座位。每位同学必须从文科和理科中选择
一科。同学们在选择科目的时候会获得一个满意值。满意值按如下的方式
得到:
1.如果第i行第秒J的同学选择了文科,则他将获得art[i][j]的满意值,如
  果选择理科,将得到science[i][j]的满意值。
2.如果第i行第J列的同学选择了文科,并且他相邻(两个格子相邻当且
  仅当它们拥有一条相同的边)的同学全部选择了文科,则他会更开
  心,所以会增加same_art[i][j]的满意值。
3.如果第i行第j列的同学选择了理科,并且他相邻的同学全部选择了理
  科,则增加same_science[i]j[]的满意值。
  小P想知道,大家应该如何选择,才能使所有人的满意值之和最大。请
告诉他这个最大值。

Input

第一行为两个正整数:n,m
接下来n术m个整数,表示art[i][j];
接下来n术m个整数.表示science[i][j];
接下来n术m个整数,表示same_art[i][j]; 

Output

输出为一个整数,表示最大的满意值之和

Sample Input

3 4
13 2 4 13
7 13 8 12
18 17 0 5

8 13 15 4
11 3 8 11
11 18 6 5

1 2 3 4
4 2 3 2
3 1 0 4

3 2 3 2
0 2 2 1
0 2 4 4

Sample Output

152

HINT

样例说明

1表示选择文科,0表示选择理科,方案如下:

1  0  0  1

0  1  0  0

1  0  0  0
 
N,M<=100,读入数据均<=500

Solution

试机的时候写的。。。贾教流。

对于一个集合选or不选产生的代价/价值可以通过新建附加点来解决。

Code

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <algorithm>
  5 
  6 #define R register
  7 #define filename ""
  8 
  9 #define maxn 100010
 10 #define maxm 600010
 11 #define inf 0x7fffffff
 12 #define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b))
 13 struct Edge {
 14     Edge *next, *rev;
 15     int to, cap;
 16 } *cur[maxn], *last[maxn], e[maxm], *ecnt = e;
 17 inline void link(R int a, R int b, R int w)
 18 {
 19     *++ecnt = (Edge) {last[a], ecnt + 1, b, w}; last[a] = ecnt;
 20     *++ecnt = (Edge) {last[b], ecnt - 1, a, 0}; last[b] = ecnt;
 21 }
 22 const int dx[4] = {1, -1, 0, 0}, dy[4] = {0, 0, 1, -1};
 23 int id[110][110], s, t, ans, q[maxn], dep[maxn], tot;
 24 inline bool bfs()
 25 {
 26     R int head = 0, tail = 1;
 27     memset(dep, -1, (tot + 1) << 2);
 28     dep[q[1] = t] = 0;
 29     while (head < tail)
 30     {
 31         R int now = q[++head];
 32         for (R Edge *iter = last[now]; iter; iter = iter -> next)
 33             if (iter -> rev -> cap && dep[iter -> to] == -1)
 34                 dep[q[++tail] = iter -> to] = dep[now] + 1;
 35     }
 36     return dep[s] != -1;
 37 }
 38 int dfs(R int x, R int f)
 39 {
 40     if (x == t) return f;
 41     R int used = 0;
 42     for (R Edge* &iter = cur[x]; iter; iter = iter -> next)
 43         if (iter -> cap && dep[iter -> to] + 1 == dep[x])
 44         {
 45             R int v = dfs(iter -> to, dmin(iter -> cap, f - used));
 46             iter -> cap -= v;
 47             iter -> rev -> cap += v;
 48             used += v;
 49             if (used == f) return f;
 50         }
 51     return used;
 52 }
 53 inline void dinic()
 54 {
 55     while (bfs())
 56     {
 57         memcpy(cur, last, (tot + 1) << 2);
 58         ans += dfs(s, inf);
 59     }
 60 }
 61 int main()
 62 {
 63 //    freopen(filename".in", "r", stdin);
 64 //    freopen(filename".out", "w", stdout);
 65     R int n, m; scanf("%d%d", &n, &m);
 66     R int anss = 0;
 67     for (R int i = 1; i <= n; ++i)
 68         for (R int j = 1; j <= m; ++j)
 69         {
 70             id[i][j] = ++tot; R int art;
 71             scanf("%d", &art); link(s, tot, art); anss += art;
 72         }
 73     t = ++tot;
 74     for (R int i = 1; i <= n; ++i)
 75         for (R int j = 1; j <= m; ++j)
 76         {
 77             R int sc; scanf("%d", &sc); anss += sc;
 78             link(id[i][j], t, sc);
 79         }
 80     for (R int i = 1; i <= n; ++i)
 81         for (R int j = 1; j <= m; ++j)
 82         {
 83             R int as; scanf("%d", &as); ++tot; anss += as;
 84             for (R int k = 0; k < 4; ++k)
 85             {
 86                 R int nx = i + dx[k], ny = j + dy[k];
 87                 if (id[nx][ny]) link(tot, id[nx][ny], inf);
 88             }
 89             link(tot, id[i][j], inf);
 90             link(s, tot, as);
 91         }
 92     for (R int i = 1; i <= n; ++i)
 93         for (R int j = 1; j <= m; ++j)
 94         {
 95             R int ss; scanf("%d", &ss); ++tot; anss += ss;
 96             for (R int k = 0; k < 4; ++k)
 97             {
 98                 R int nx = i + dx[k], ny = j + dy[k];
 99                 if (id[nx][ny]) link(id[nx][ny], tot, inf);
100             }
101             link(id[i][j], tot, inf);
102             link(tot, t, ss);
103         }
104     dinic();
105     printf("%d
", anss - ans);
106     return 0;
107 }
原文地址:https://www.cnblogs.com/cocottt/p/6781847.html