这个题太恶心了。。。并不想继续做了。。。

本代码在bzoj上TLE!

大致说一下思路: 建立ST,首先由S连边(S,u,a)a代表学文的分数,连向T(u,T,b)b表示学理的分数,这样构造出了两个人独立的分数。

然后考虑联合分数,对于相邻的两个点xy,看下图(盗个图:

  设xy都学文的分数为w1,都学理的分数为w2,则a=w1/2,b=w1/2,c=w2/2,d=w2/2,e=(w1+w2)/2,每一种割与其对应的亏损分数如下:

  a+b          -w1      都学理->w2

  c+d          -w2      都学文->w1

  a+d+e       -w1-w2     不同->   0

  c+d+e       -w1-w2    ...

  注意双向边e,我们是变成两条有向边加入网络,而又因为我们求最小割用的是最大流的算法,所以这条边可以看作是一条双向且权值为e的边。

  然后把权值*2,解决精度问题。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 105; /////////////////////////////////////////////
const int maxv = maxn * maxn * 2;
const int inf = INT_MAX;
int n, m, s, t, v;
struct edge {
int from;
int to;
int cap;
};
vector<edge> edges;
vector<int> G[maxv];
int dist[maxv], iter[maxv];
int z[maxv][maxv];
bool zz[maxv][maxv];
inline int read() {
char c = getchar();
int f = 1, x = 0;
while (!isdigit(c)) {
if (c == '-')
f = -1;
c = getchar();
}
while (isdigit(c))
x = x * 10 + c - '0', c = getchar();
return x * f;
}
inline void add_edge(int from, int to, int cap) {
edges.push_back((edge){from, to, cap});
edges.push_back((edge){to, from, 0});
int m = edges.size();
G[from].push_back(m - 2);
G[to].push_back(m - 1);
}
inline void bfs(int s) {
memset(dist, -1, sizeof(dist));
dist[s] = 0;
queue<int> q;
q.push(s);
while (!q.empty()) {
int u = q.front();
q.pop();
for (int i = 0; i < G[u].size(); i++) {
edge &e = edges[G[u][i]];
if (e.cap > 0 && dist[e.to] == -1) {
dist[e.to] = dist[u] + 1;
q.push(e.to);
}
}
}
}
inline int dfs(int s, int t, int flow) {
if (s == t)
return flow;
for (int &i = iter[s]; i < G[s].size(); i++) {
edge &e = edges[G[s][i]];
if (e.cap > 0 && dist[e.to] > dist[s]) {
int d = dfs(e.to, t, min(flow, e.cap));
if (d > 0) {
e.cap -= d;
edges[G[s][i] ^ 1].cap += d;
return d;
}
}
}
return 0;
}
inline int dinic(int s, int t) {
int flow = 0;
while (1) {
bfs(s);
if (dist[t] == -1)
return flow;
memset(iter, 0, sizeof(iter));
int F;
while (F = dfs(s, t, inf))
flow += F;
}
}
int main() {
// freopen("input", "r", stdin); //////////////////////////
memset(z, 0, sizeof(z));
memset(zz, 0, sizeof(zz));
scanf("%d %d", &n, &m);
s = 0; //文科
t = n * m + 1; //理科
v = t + 1;
int ans = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
int x;
x = read();
x <<= 1;
z[s][(i - 1) * m + j] += x;
zz[s][(i - 1) * m + j] = 1;
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
int x;
x = read();
x <<= 1;
z[(i - 1) * m + j][t] += x;
zz[(i - 1) * m + j][t] = 1;
}
for (int i = 1; i < n; i++) {
for (int j = 1; j <= m; j++) {
int x;
x = read();
z[(i - 1) * m + j][i * m + j] += x;
z[s][(i - 1) * m + j] += x;
z[s][i * m + j] += x;
zz[(i - 1) * m + j][i * m + j] = 1;
zz[s][(i - 1) * m + j] = 1;
zz[s][i * m + j] = 1;
add_edge((i - 1) * m + j, i * m + j, x);
add_edge(i * m + j, (i - 1) * m + j, x);
}
}
for (int i = 1; i < n; i++) {
for (int j = 1; j <= m; j++) {
int x;
x = read();
z[(i - 1) * m + j][i * m + j] += x;
z[(i - 1) * m + j][t] += x;
z[i * m + j][t] += x;
zz[(i - 1) * m + j][i * m + j] = 1;
zz[(i - 1) * m + j][t] = 1;
zz[i * m + j][t] = 1;
add_edge((i - 1) * m + j, i * m + j, x);
add_edge(i * m + j, (i - 1) * m + j, x);
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j < m; j++) {
int x;
x = read();
z[(i - 1) * m + j][(i - 1) * m + j + 1] += x;
z[s][(i - 1) * m + j] += x;
z[s][(i - 1) * m + j + 1] += x;
zz[(i - 1) * m + j][(i - 1) * m + j + 1] = 1;
zz[s][(i - 1) * m + j] = 1;
zz[s][(i - 1) * m + j + 1] = 1;
add_edge((i - 1) * m + j, (i - 1) * m + j + 1, x);
add_edge((i - 1) * m + j + 1, (i - 1) * m + j, x);
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j < m; j++) {
int x;
x = read();
z[(i - 1) * m + j][(i - 1) * m + j + 1] += x;
z[(i - 1) * m + j][t] += x;
z[(i - 1) * m + j + 1][t] += x;
zz[(i - 1) * m + j][(i - 1) * m + j + 1] = 1;
zz[(i - 1) * m + j][t] = 1;
zz[(i - 1) * m + j + 1][t] = 1;
add_edge((i - 1) * m + j, (i - 1) * m + j + 1, x);
add_edge((i - 1) * m + j + 1, (i - 1) * m + j, x);
}
}
for (int i = 1; i < t; i++) {
ans += z[s][i];
ans += z[i][t];
if (zz[s][i])
add_edge(s, i, z[s][i]);
if (zz[i][t])
add_edge(i, t, z[i][t]);
}
for (int i = 1; i < t; i++) {
for (int j = 1; j < t; j++) {
if (zz[i][j]) {
add_edge(i, j, z[i][j]);
add_edge(j, i, z[i][j]);
}
}
}
/* for (int i = 0; i < v; i++) {
cout << "For " << i << ':' << endl;
for (int j = 0; j < G[i].size(); j++) {
edge &e = edges[G[i][j]];
if (e.cap > 0)
cout << "to " << e.to << " cap " << e.cap << endl;
}
}*/
ans -= dinic(s, t);
printf("%d\n", ans >> 1);
}

[bzoj2127]happiness——最小割的更多相关文章

  1. 【BZOJ2127】happiness 最小割

    题目大意:有一个$n\times m$的矩阵,矩阵的每个位置上有一个同学,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友.这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦 ...

  2. [置顶] [BZOJ]2127: happiness 最小割

    happiness: Description 高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友.这学期要分文理科了,每个同学对于选择文科与理科有着自己 ...

  3. [BZOJ2127]happiness-[网络流-最小割]

    Description 传送门 Solution 按照最小割的思路考虑. 根据题意,当两个人都选文(理),需要砍掉两个人都选理(文)的加成:如果两个人选的不一样,就要都砍掉. 这是一个网络流建模的套路 ...

  4. [国家集训队]happiness 最小割 BZOJ 2127

    题目描述 高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友.这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦值,而一对好朋友如果能同时选文 ...

  5. BZOJ 2127 / Luogu P1646 [国家集训队]happiness (最小割)

    题面 BZOJ传送门 Luogu传送门 分析 这道题又出现了二元关系,于是我们只需要解方程确定怎么连边就行了 假设跟SSS分在一块是选文科,跟TTT分在一块是选理科,先加上所有的收益,再来考虑如何让需 ...

  6. luogu P1646 [国家集训队]happiness (最小割)

    高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友.这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦值,而一对好朋友如果能同时选文科或者理科 ...

  7. BZOJ 2127: happiness [最小割]

    2127: happiness Time Limit: 51 Sec  Memory Limit: 259 MBSubmit: 1815  Solved: 878[Submit][Status][Di ...

  8. BZOJ 2127: happiness(最小割解决集合划分)

    Time Limit: 51 Sec  Memory Limit: 259 MBSubmit: 2350  Solved: 1138[Submit][Status][Discuss] Descript ...

  9. 【BZOJ2127】happiness(最小割)

    [BZOJ2127]happiness(最小割) 题面 Description 高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友.这学期要分文理科了, ...

随机推荐

  1. C语言实例解析精粹学习笔记——26

    实例26:阿拉伯数字转换为罗马数字,将一个整数n(1~9999)转换为罗马数字,其中数字和罗马数字的对应关系如下: 原书中的开发环境很老,我也没有花心思去研究.自己在codeblocks中进行开发的, ...

  2. sigaction函数

    sigaction函数是设置信号处理的接口.比signal函数更健壮 #include <signal.h> int sigaction(int signum, const struct ...

  3. QWidget 自带的最大化,最小化,关闭按键的设置

    使用函数 setWindowFlags 参数: CustomizeWindowHint 去掉窗口所有自带按钮 Qt::CustomizeWindowHint | Qt::WindowCloseButt ...

  4. SGU 169 numbers 数学

    169.Numbers Let us call P(n) - the product of all digits of number n (in decimal notation). For exam ...

  5. keil 使用C++编程主要要点

    1.中断处理,添加一下宏定义.如果不添加,中断服务函数不会链接到下载文件中:发生中断后,会停留在xxx.s文件的 "B ."语句. #ifdef __cplusplus exter ...

  6. MyBatis---自动创建表

    该项目基于Maven实现 该项目实现了在项目启动时,对数据库表进行操作 源码下载 实现步骤: 1.向pom.xml文件添加maven依赖 <dependency> <groupId& ...

  7. laravel5.5配置信息

    目录 1 环境配置 1.1 检索环境配置 1.2 确定当前环境 2 访问配置值 3 配置缓存 4 维护模式 配置文件在config目录下,为了便于不同人员的开发,我们可以使用不同的.env文件来配置各 ...

  8. PyCharm 解决有些库(函数)没有代码提示

    问题描述: 如图,当输入 im. 没有智能提示第三库相应的函数或其他提示. 解决方案: python是动态强类型语言,IDE无法判断Image.open("panda.png")的 ...

  9. windows下使用RoboCopy命令进行文件夹增量备份

    RoboCopy,它是一个命令行的目录复制命令,自从Windows NT 4.0 开始就成为windows 资源工具包的一部分,然后在Windows Vista.Windows 7和 Windows ...

  10. 孤荷凌寒自学python第二十一天初识python的类

    孤荷凌寒自学python第二十一天初识python的类 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 类是面向对象的编程语言非常重要的概念. 编程语言的进化史中从顺序编程到结构化编程,最后才 ...