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. Spring MVC 方法注解拦截器

    应用场景,在方法级别对本次调用进行鉴权,如api接口中有个用户唯一标示accessToken,对于有accessToken的每次请求可以在方法加一个拦截器,获得本次请求的用户,存放到request或者 ...

  2. RabbitMQ 与 AMQP路由

    概述 RabbitMQ(MQ 为 MessageQueue) 是一个消息队列,主要是用来实现应用程序的异步和解耦,同时起到消息缓冲.消息分发作用 消息队列 消息(Message)是指应用间传送的数据, ...

  3. html5本地存储之localstorage 、本地数据库、sessionStorage简单使用示例

    这篇文章主要介绍了html5本地存储的localstorage .本地数据库.sessionStorage简单使用示例,需要的朋友可以参考下 html5的一个非常cool的功能,就是web stora ...

  4. 设计模式--原型模式C++实现

    原型模式C++实现 1定义 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象 2类图 3实现 class Prototype { protected: Prototype(); publ ...

  5. Spring入门3.AOP编程

    Spring入门3.AOP编程 代码下载: 链接: http://pan.baidu.com/s/11mYEO 密码: x7wa 前言: 前面学习的知识是Spring在Java项目中的IoC或DJ,这 ...

  6. nfc功能读写 demo

    点此下载//这个demo是把这个程序作为一个手机启动选择的,只要一扫到卡片就会跳转到这个Activity. 只在当前Activity中有效参考:http://blog.csdn.net/zoeice/ ...

  7. eureka -1 - 介绍

    eureka ,服务发现注册中心 eureka 包含server, client两部分. eureka server,服务发现组件,各个微服务启动的时候会向server注册自己的信息(ip,hostn ...

  8. Django之model操作(续)

    Django中的源码续 ################################################## # PUBLIC METHODS THAT RETURN A QUERYS ...

  9. 什么是web?什么是web服务器?什么是应用服务器?

    1.什么是Web? 简单来说,Web就是在Http协议基础之上,利用浏览器进行访问的网站.目前来看最常用的意义是指在 Intenet 上和 HTML 相关的部分.换句话说,目前在 Intenet 上通 ...

  10. L147 Low Cost Study Has High Impact Results For Premature Babies

    No one knows exactly why some babies are born prematurely(早产), but some of the smallest premature ba ...