LOJ2321. 「清华集训 2017」无限之环【费用流】
很好的一道网络里题
首先想插头DP的还是出门左转10分代码吧
然后考虑怎么网络流
首先要保证没有漏水
也就是说每个接口一定要有对应的接口
那么发现每个点只有可能和上下左右四个点产生联通关系
所以不妨对图进行黑白染色
然后把源点连向所有的黑色格子,所有的黑色格子向白色格子连边,所有的白色格子向汇点连边
那么具体怎么处理每个格子的贡献?
把每个格子分成四个点分别表示上下左右
然后我们发现需要转动的只有三种
- 只有一个接口
- 有两个接口形成L形
- 有三个接口
然后考虑一个接口,相反方向连边代价是2,其他两个方向是1
L形,转九十度和转二百七十度是代价相等的,然后发现其实如果不考虑顺序的影响因素,本质上只有一个位置变成了另外一个位置
那么旋转180度也就是两个位置同时变化,刚好是变化一次代价为1,是不是很神奇呢
然后三个接口的情况类似,需要分类讨论,但是并不复杂,和两个的情况类似
然后建图建完了就可以费用流了
我怎么这么慢。。。
//Author: dream_maker
#include<bits/stdc++.h>
using namespace std;
//----------------------------------------------
//typename
typedef long long ll;
typedef pair<int, int> pi;
//convenient for
#define fu(a, b, c) for (int a = b; a <= c; ++a)
#define fd(a, b, c) for (int a = b; a >= c; --a)
#define fv(a, b) for (int a = 0; a < (signed)b.size(); ++a)
//inf of different typename
const int INF_of_int = 1e9;
const ll INF_of_ll = 1e18;
//fast read and write
template <typename T>
void Read(T &x) {
bool w = 1;x = 0;
char c = getchar();
while (!isdigit(c) && c != '-') c = getchar();
if (c == '-') w = 0, c = getchar();
while (isdigit(c)) {
x = (x<<1) + (x<<3) + c -'0';
c = getchar();
}
if (!w) x = -x;
}
template <typename T>
void Write(T x) {
if (x < 0) {
putchar('-');
x = -x;
}
if (x > 9) Write(x / 10);
putchar(x % 10 + '0');
}
//----------------------------------------------
const int N = 1.6e7 + 10;
const int M = 2e3 + 10;
namespace Min_Cost_Max_Flow {
struct Edge{
int u, v, cap, flow, cost;
};
int S, T;
int dis[N], pre[N], f[N];
bool inq[N];
vector<Edge> E;
vector<int> G[N];
void add(int u, int v, int cap, int cost) {
E.push_back((Edge){u, v, cap, 0, cost});
E.push_back((Edge){v, u, 0, 0, -cost});
int m = E.size();
G[u].push_back(m - 2);
G[v].push_back(m - 1);
}
bool spfa(int &flow, int &cost) {
static queue<int> q;
fu(i, 1, T) dis[i] = INF_of_int;
dis[S] = 0;
f[S] = INF_of_int;
q.push(S);
while(!q.empty()){
int u = q.front();q.pop();
inq[u] = 0;
fv(i, G[u]) {
Edge e = E[G[u][i]];
if (e.cap > e.flow && dis[e.v] > dis[u] + e.cost) {
dis[e.v] = dis[u] + e.cost;
pre[e.v] = G[u][i];
f[e.v] = min(f[u], e.cap - e.flow);
if (!inq[e.v]) inq[e.v] = 1, q.push(e.v);
}
}
}
if (dis[T] == INF_of_int) return 0;
flow += f[T];
cost += f[T] * dis[T];
int u = T;
while (u != S) {
E[pre[u]].flow += f[T];
E[pre[u] ^ 1].flow -= f[T];
u = E[pre[u]].u;
}
return 1;
}
pi mcmf() {
int flow = 0, cost = 0;
while(spfa(flow, cost));
return pi(flow, cost);
}
};
int n, m, cnt = 0;
struct Point{
bool l, r, u, d;
int typ;
//typ = 1 one interface
//typ = 2 tow interfaces in different line
//typ = 3 tow interfaces in the same line (useless)
//typ = 4 three interfaces
//typ = 5 four interfaces (useless)
int l_id, r_id, u_id, d_id;
}g[M][M];
int mx[4] = {-1, 0, 1, 0};
int my[4] = {0, 1, 0, -1};
void insert_single_point(Point p, int typ) {
if (typ) { //black
if (p.l) Min_Cost_Max_Flow::add(Min_Cost_Max_Flow::S, p.l_id, 1, 0);
if (p.r) Min_Cost_Max_Flow::add(Min_Cost_Max_Flow::S, p.r_id, 1, 0);
if (p.u) Min_Cost_Max_Flow::add(Min_Cost_Max_Flow::S, p.u_id, 1, 0);
if (p.d) Min_Cost_Max_Flow::add(Min_Cost_Max_Flow::S, p.d_id, 1, 0);
} else { //white
if (p.l) Min_Cost_Max_Flow::add(p.l_id, Min_Cost_Max_Flow::T, 1, 0);
if (p.r) Min_Cost_Max_Flow::add(p.r_id, Min_Cost_Max_Flow::T, 1, 0);
if (p.u) Min_Cost_Max_Flow::add(p.u_id, Min_Cost_Max_Flow::T, 1, 0);
if (p.d) Min_Cost_Max_Flow::add(p.d_id, Min_Cost_Max_Flow::T, 1, 0);
}
}
void add_edge_single_point_case_1(Point p, int typ) {
if (p.l) {
if (typ) {
Min_Cost_Max_Flow::add(p.l_id, p.r_id, 1, 2);
Min_Cost_Max_Flow::add(p.l_id, p.u_id, 1, 1);
Min_Cost_Max_Flow::add(p.l_id, p.d_id, 1, 1);
} else {
Min_Cost_Max_Flow::add(p.r_id, p.l_id, 1, 2);
Min_Cost_Max_Flow::add(p.u_id, p.l_id, 1, 1);
Min_Cost_Max_Flow::add(p.d_id, p.l_id, 1, 1);
}
}
if (p.r) {
if (typ) {
Min_Cost_Max_Flow::add(p.r_id, p.l_id, 1, 2);
Min_Cost_Max_Flow::add(p.r_id, p.u_id, 1, 1);
Min_Cost_Max_Flow::add(p.r_id, p.d_id, 1, 1);
} else {
Min_Cost_Max_Flow::add(p.l_id, p.r_id, 1, 2);
Min_Cost_Max_Flow::add(p.u_id, p.r_id, 1, 1);
Min_Cost_Max_Flow::add(p.d_id, p.r_id, 1, 1);
}
}
if (p.u) {
if (typ) {
Min_Cost_Max_Flow::add(p.u_id, p.d_id, 1, 2);
Min_Cost_Max_Flow::add(p.u_id, p.l_id, 1, 1);
Min_Cost_Max_Flow::add(p.u_id, p.r_id, 1, 1);
} else {
Min_Cost_Max_Flow::add(p.d_id, p.u_id, 1, 2);
Min_Cost_Max_Flow::add(p.l_id, p.u_id, 1, 1);
Min_Cost_Max_Flow::add(p.r_id, p.u_id, 1, 1);
}
}
if (p.d) {
if (typ) {
Min_Cost_Max_Flow::add(p.d_id, p.u_id, 1, 2);
Min_Cost_Max_Flow::add(p.d_id, p.l_id, 1, 1);
Min_Cost_Max_Flow::add(p.d_id, p.r_id, 1, 1);
} else {
Min_Cost_Max_Flow::add(p.u_id, p.d_id, 1, 2);
Min_Cost_Max_Flow::add(p.l_id, p.d_id, 1, 1);
Min_Cost_Max_Flow::add(p.r_id, p.d_id, 1, 1);
}
}
}
void add_edge_single_point_case_2(Point p, int typ) {
if (p.l) {
if (typ) {
Min_Cost_Max_Flow::add(p.l_id, p.r_id, 1, 1);
} else {
Min_Cost_Max_Flow::add(p.r_id, p.l_id, 1, 1);
}
}
if (p.r) {
if (typ) {
Min_Cost_Max_Flow::add(p.r_id, p.l_id, 1, 1);
} else {
Min_Cost_Max_Flow::add(p.l_id, p.r_id, 1, 1);
}
}
if (p.u) {
if (typ) {
Min_Cost_Max_Flow::add(p.u_id, p.d_id, 1, 1);
} else {
Min_Cost_Max_Flow::add(p.d_id, p.u_id, 1, 1);
}
}
if (p.d) {
if (typ) {
Min_Cost_Max_Flow::add(p.d_id, p.u_id, 1, 1);
} else {
Min_Cost_Max_Flow::add(p.u_id, p.d_id, 1, 1);
}
}
}
void add_edge_single_point_case_3(Point p, int typ) {
if (!p.l) {
if (typ) {
Min_Cost_Max_Flow::add(p.r_id, p.l_id, 1, 2);
Min_Cost_Max_Flow::add(p.u_id, p.l_id, 1, 1);
Min_Cost_Max_Flow::add(p.d_id, p.l_id, 1, 1);
} else {
Min_Cost_Max_Flow::add(p.l_id, p.r_id, 1, 2);
Min_Cost_Max_Flow::add(p.l_id, p.u_id, 1, 1);
Min_Cost_Max_Flow::add(p.l_id, p.d_id, 1, 1);
}
}
if (!p.r) {
if (typ) {
Min_Cost_Max_Flow::add(p.l_id, p.r_id, 1, 2);
Min_Cost_Max_Flow::add(p.u_id, p.r_id, 1, 1);
Min_Cost_Max_Flow::add(p.d_id, p.r_id, 1, 1);
} else {
Min_Cost_Max_Flow::add(p.r_id, p.l_id, 1, 2);
Min_Cost_Max_Flow::add(p.r_id, p.u_id, 1, 1);
Min_Cost_Max_Flow::add(p.r_id, p.d_id, 1, 1);
}
}
if (!p.u) {
if (typ) {
Min_Cost_Max_Flow::add(p.d_id, p.u_id, 1, 2);
Min_Cost_Max_Flow::add(p.l_id, p.u_id, 1, 1);
Min_Cost_Max_Flow::add(p.r_id, p.u_id, 1, 1);
} else {
Min_Cost_Max_Flow::add(p.u_id, p.d_id, 1, 2);
Min_Cost_Max_Flow::add(p.u_id, p.l_id, 1, 1);
Min_Cost_Max_Flow::add(p.u_id, p.r_id, 1, 1);
}
}
if (!p.d) {
if (typ) {
Min_Cost_Max_Flow::add(p.u_id, p.d_id, 1, 2);
Min_Cost_Max_Flow::add(p.l_id, p.d_id, 1, 1);
Min_Cost_Max_Flow::add(p.r_id, p.d_id, 1, 1);
} else {
Min_Cost_Max_Flow::add(p.d_id, p.u_id, 1, 2);
Min_Cost_Max_Flow::add(p.d_id, p.l_id, 1, 1);
Min_Cost_Max_Flow::add(p.d_id, p.r_id, 1, 1);
}
}
}
void add_edge_between_points(Point a, Point b, int dir) {
if (dir == 0) Min_Cost_Max_Flow::add(a.u_id, b.d_id, 1, 0);
if (dir == 1) Min_Cost_Max_Flow::add(a.r_id, b.l_id, 1, 0);
if (dir == 2) Min_Cost_Max_Flow::add(a.d_id, b.u_id, 1, 0);
if (dir == 3) Min_Cost_Max_Flow::add(a.l_id, b.r_id, 1, 0);
}
int main() {
#ifdef dream_maker
freopen("input.txt", "r", stdin);
#endif
Read(n);Read(m);
int sum = 0;
Min_Cost_Max_Flow::S = 0;
Min_Cost_Max_Flow::T = n * m * 4 + 1;
fu(i, 1, n) {
fu(j, 1, m) {
int w;Read(w);
g[i][j].u = (w & (1 << 0)); g[i][j].u_id = ++cnt;
g[i][j].r = (w & (1 << 1)); g[i][j].r_id = ++cnt;
g[i][j].d = (w & (1 << 2)); g[i][j].d_id = ++cnt;
g[i][j].l = (w & (1 << 3)); g[i][j].l_id = ++cnt;
int num = g[i][j].u + g[i][j].r + g[i][j].d + g[i][j].l;
sum += num;
if (num == 1) {
add_edge_single_point_case_1(g[i][j], (i + j) & 1);
} else if (num == 2) {
if ((!g[i][j].u || !g[i][j].d) && (!g[i][j].l || !g[i][j].r))
add_edge_single_point_case_2(g[i][j], (i + j) & 1);
} else if (num == 3) {
add_edge_single_point_case_3(g[i][j], (i + j) & 1);
}
insert_single_point(g[i][j], (i + j) & 1);
}
}
fu(i, 1, n) {
fu(j, 1, m) {
if ((i + j) & 1) {
fu(k, 0, 3) {
int ni = i + mx[k], nj = j + my[k];
if (ni < 1 || ni > n || nj < 1 || nj > m) continue;
add_edge_between_points(g[i][j], g[ni][nj], k);
}
}
}
}
pi res = Min_Cost_Max_Flow::mcmf();
if (res.first * 2 != sum) Write(-1);
else Write(res.second);
return 0;
}
LOJ2321. 「清华集训 2017」无限之环【费用流】的更多相关文章
- Loj #2321. 「清华集训 2017」无限之环
Loj #2321. 「清华集训 2017」无限之环 曾经有一款流行的游戏,叫做 *Infinity Loop***,先来简单的介绍一下这个游戏: 游戏在一个 \(n \times m\) 的网格状棋 ...
- UOJ #2321. 「清华集训 2017」无限之环
首先裂点表示四个方向 一条边上都有插头或者都不有插头,相当于满足流量平衡 最大流 = 插头个数*2时有解 然后求最小费用最大流 黑白染色分别连原点汇点
- [LOJ#2330]「清华集训 2017」榕树之心
[LOJ#2330]「清华集训 2017」榕树之心 试题描述 深秋.冷风吹散了最后一丝夏日的暑气,也吹落了榕树脚下灌木丛的叶子.相识数年的Evan和Lyra再次回到了小时候见面的茂盛榕树之下.小溪依旧 ...
- [LOJ#2329]「清华集训 2017」我的生命已如风中残烛
[LOJ#2329]「清华集训 2017」我的生命已如风中残烛 试题描述 九条可怜是一个贪玩的女孩子. 这天她在一堵墙钉了 \(n\) 个钉子,第 \(i\) 个钉子的坐标是 \((x_i,y_i)\ ...
- Loj #2331. 「清华集训 2017」某位歌姬的故事
Loj #2331. 「清华集训 2017」某位歌姬的故事 IA 是一名会唱歌的女孩子. IOI2018 就要来了,IA 决定给参赛选手们写一首歌,以表达美好的祝愿.这首歌一共有 \(n\) 个音符, ...
- Loj #2324. 「清华集训 2017」小 Y 和二叉树
Loj #2324. 「清华集训 2017」小 Y 和二叉树 小Y是一个心灵手巧的OIer,她有许多二叉树模型. 小Y的二叉树模型中,每个结点都具有一个编号,小Y把她最喜欢的一个二叉树模型挂在了墙上, ...
- Loj 2320.「清华集训 2017」生成树计数
Loj 2320.「清华集训 2017」生成树计数 题目描述 在一个 \(s\) 个点的图中,存在 \(s-n\) 条边,使图中形成了 \(n\) 个连通块,第 \(i\) 个连通块中有 \(a_i\ ...
- loj #2325. 「清华集训 2017」小Y和恐怖的奴隶主
#2325. 「清华集训 2017」小Y和恐怖的奴隶主 内存限制:256 MiB时间限制:2000 ms标准输入输出 题目类型:传统评测方式:文本比较 题目描述 "A fight? Co ...
- [LOJ#2328]「清华集训 2017」避难所
[LOJ#2328]「清华集训 2017」避难所 试题描述 "B君啊,你当年的伙伴都不在北京了,为什么你还在北京呢?" "大概是因为出了一些事故吧,否则这道题就不叫避难所 ...
随机推荐
- 那些年java MD5加密字符编码的坑
相信做过MD5加密的童鞋都遇到过字符编码的坑,一般加密出来的结果和其他人不一样都是字符编码不一致导致的,比如类文件的字符编码.浏览器的字符编码等和对方不一致,所以就需要转码统一字符. 以下是笔者转码过 ...
- c++之迭代器失效
1.首先从一到题目开始谈说起迭代器失效.有时我们很自然并且自信地 用下面方法删除vector元素: #include <iostream>#include <stdio.h># ...
- 配置了java环境变量后不起作用
我的电脑上装了好几个版本的jdk,有jdk1.6.jdk1.8.但是我的环境变量是设置jdk1.6的.然而打开cmd,查看Java版本却显示的是1.8,这让我百思不得其解.后来发现了问题. 问题:在p ...
- linux文件的一些特殊权限
一些特殊权限 虽然我们通常看到一个八进制的权限掩码用三位数字来表示,但是从技术层面 上来讲,用四位数字来表示它更确切些. 为什么呢?因为,除了读取,写入,和执 行权限之外,还有其它的,较少用到的权限设 ...
- LeetCode第[73]题(Java):Set Matrix Zeroes(矩阵置0)
题目:矩阵置0 难度:Easy 题目内容: Given a m x n matrix, if an element is 0, set its entire row and column to 0. ...
- SpringAOP源码分析总结
1.Advisor(增强器):充当Advice和Pointcut的适配器,类似使用Aspect的@Aspect注解的类(前一章节所述).一般有advice和pointcut属性. 祖先接口为org.s ...
- BT5 set_config各个选项的配置
最近研究了一下bt5的社会工程学工具SET,本来国内的bt5的资料就很少了,详细分析SET的资料就更少了,在各大网站找了找,都不靠谱,还是得自力更生啊,我在这里就把自己的过程写下来,希望对大家有点帮助 ...
- superset dashboard 设置自动刷新
因为发现了,自己制作了看板dashboard,却不会刷新,很奇怪. 那这样不是太傻了.难道要业务人员一个个去点吗? 一定有刷新的,然后和无头苍蝇在网上找了半天. 实际刷新的位置在这里. 具体设置有很多 ...
- 嵌套类,PIMPL
body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...
- 在QT中使用静态对象
最近做教研室的项目,需要只能存在一个接收数据的线程,那么我就想把这个线程设置成一个静态对象.但是在connect信号与槽的时候出了一点问题,最后搞好了,现在这mark一下: 比如说一个声明了一个静态的 ...