LINK


很好的一道网络里题

首先想插头DP的还是出门左转10分代码吧

然后考虑怎么网络流

首先要保证没有漏水

也就是说每个接口一定要有对应的接口

那么发现每个点只有可能和上下左右四个点产生联通关系

所以不妨对图进行黑白染色

然后把源点连向所有的黑色格子,所有的黑色格子向白色格子连边,所有的白色格子向汇点连边

那么具体怎么处理每个格子的贡献?

把每个格子分成四个点分别表示上下左右

然后我们发现需要转动的只有三种

  1. 只有一个接口
  2. 有两个接口形成L形
  3. 有三个接口

然后考虑一个接口,相反方向连边代价是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」无限之环【费用流】的更多相关文章

  1. Loj #2321. 「清华集训 2017」无限之环

    Loj #2321. 「清华集训 2017」无限之环 曾经有一款流行的游戏,叫做 *Infinity Loop***,先来简单的介绍一下这个游戏: 游戏在一个 \(n \times m\) 的网格状棋 ...

  2. UOJ #2321. 「清华集训 2017」无限之环

    首先裂点表示四个方向 一条边上都有插头或者都不有插头,相当于满足流量平衡 最大流 = 插头个数*2时有解 然后求最小费用最大流 黑白染色分别连原点汇点

  3. [LOJ#2330]「清华集训 2017」榕树之心

    [LOJ#2330]「清华集训 2017」榕树之心 试题描述 深秋.冷风吹散了最后一丝夏日的暑气,也吹落了榕树脚下灌木丛的叶子.相识数年的Evan和Lyra再次回到了小时候见面的茂盛榕树之下.小溪依旧 ...

  4. [LOJ#2329]「清华集训 2017」我的生命已如风中残烛

    [LOJ#2329]「清华集训 2017」我的生命已如风中残烛 试题描述 九条可怜是一个贪玩的女孩子. 这天她在一堵墙钉了 \(n\) 个钉子,第 \(i\) 个钉子的坐标是 \((x_i,y_i)\ ...

  5. Loj #2331. 「清华集训 2017」某位歌姬的故事

    Loj #2331. 「清华集训 2017」某位歌姬的故事 IA 是一名会唱歌的女孩子. IOI2018 就要来了,IA 决定给参赛选手们写一首歌,以表达美好的祝愿.这首歌一共有 \(n\) 个音符, ...

  6. Loj #2324. 「清华集训 2017」小 Y 和二叉树

    Loj #2324. 「清华集训 2017」小 Y 和二叉树 小Y是一个心灵手巧的OIer,她有许多二叉树模型. 小Y的二叉树模型中,每个结点都具有一个编号,小Y把她最喜欢的一个二叉树模型挂在了墙上, ...

  7. Loj 2320.「清华集训 2017」生成树计数

    Loj 2320.「清华集训 2017」生成树计数 题目描述 在一个 \(s\) 个点的图中,存在 \(s-n\) 条边,使图中形成了 \(n\) 个连通块,第 \(i\) 个连通块中有 \(a_i\ ...

  8. loj #2325. 「清华集训 2017」小Y和恐怖的奴隶主

    #2325. 「清华集训 2017」小Y和恐怖的奴隶主 内存限制:256 MiB时间限制:2000 ms标准输入输出 题目类型:传统评测方式:文本比较   题目描述 "A fight? Co ...

  9. [LOJ#2328]「清华集训 2017」避难所

    [LOJ#2328]「清华集训 2017」避难所 试题描述 "B君啊,你当年的伙伴都不在北京了,为什么你还在北京呢?" "大概是因为出了一些事故吧,否则这道题就不叫避难所 ...

随机推荐

  1. harbor 管理Helm Chart包

    官方网站:https://github.com/goharbor/harbor官方用户手册:https://github.com/goharbor/harbor/blob/master/docs/us ...

  2. spring boot 登录认证

    玩转spring boot——简单登录认证 https://www.cnblogs.com/GoodHelper/p/6343190.html 玩转spring boot——简单登录认证 https: ...

  3. Android -- 网络图片查看器,网络html查看器, 消息机制, 消息队列,线程间通讯

    1. 原理图 2. 示例代码 (网络图片查看器) (1)  HttpURLConnection (2) SmartImageView (开源框架:https://github.com/loopj/an ...

  4. Struts2 入门实例

    一.最简登录 Demo:login.jsp——web.xml——struts.xml——LoginAction.java——struts.xml——index.jsp 1.下载 Struts2 框架: ...

  5. RabbitMQ 之 订阅模式 Publish/Subscribe

    模型图 我们之前学习的都是一个消息只能被一个消费者消费,那么如果我想发一个消息 能被多个消费者消费,这时候怎么办? 这时候我们就得用到了消息中的发布订阅模型 在前面的教程中,我们创建了一个工作队列,都 ...

  6. 虚拟机中的Linux安装VMware Tools的方法

    先检查虚拟机是否能上网 一:安装VMware Tools的之前必装的工具套件方法如下: Centos安装VMware Tools: [root@piaoyun-vm vmware-tools-dist ...

  7. Kafka消息topic分区

      kafka是为分布式环境设计的,因此如果日志文件,其实也可以理解成消息数据库,放在同一个地方,那么必然会带来可用性的下降,一挂全挂,如果全量拷贝到所有的机器上,那么数据又存在过多的冗余,而且由于每 ...

  8. ZooKeeper原理 --------这可能是把ZooKeeper概念讲的最清楚的一篇文章

    相信大家对 ZooKeeper 应该不算陌生,但是你真的了解 ZooKeeper 是什么吗?如果别人/面试官让你讲讲 ZooKeeper 是什么,你能回答到哪个地步呢? 我本人曾经使用过 ZooKee ...

  9. Python 基础教程

    Python 基础教程 Python是一种解释型.面向对象.动态数据类型的高级程序设计语言. Python由Guido van Rossum于1989年底发明,第一个公开发行版发行于1991年. 像P ...

  10. http协议与soap协议区别