$n \leq 50$

sol:

放一个在 $x$ 处拐弯的 $L$ 形石头相当于在水平和垂直方向上各选一个与 $x$ 相邻的点,全局不能重复选

最小化危险度,相当于满足这些限制的情况下石头盖住的点危险度越大越好,而石头有各种各样的限制,考虑费用流

这是一个“只能增广 m 次的最大费用可行流”问题,我们增广到 m 次或者找出来的最长路为负即可

为了满足“不重复选”,可以拆点,每个入点向出点连流量 1,费用为危险度的边

因为每个危险点左右和上下各能选一个,相当于“每头牛都要分到一瓶可乐和一份午饭”(忘了这道题题号了...),可以把每个不危险的点分成“可乐”和“午饭”两类

因为选的两个不危险的点行数奇偶性不同,所以可以考虑按行数奇偶把非危险点分成两类

$S \space \rightarrow \space 每个行数为奇数的非危险点 \space \rightarrow \space 相邻的入点$

$相邻的出点 \space \rightarrow \space 每个行数为偶数的非危险点 \space \rightarrow \space T$

以上两类边流量 1,费用 0

然后愉快的流

#include<bits/stdc++.h>
#define LL long long
using namespace std;
inline int read()
{
int x = ,f = ;char ch = getchar();
for(;!isdigit(ch);ch = getchar())if(ch == '-') f = -f;
for(;isdigit(ch);ch = getchar())x = * x + ch - '';
return x * f;
}
const int maxn = ,maxm = ,oo = ;
struct ZKW
{
int head[maxn], nx[maxn], inq[maxn], vis[maxn], dis[maxn];
int n, m, s, t, ans, cost;
queue<int> q;
struct Edge
{
int from, to, caps, cost;
Edge(){}
Edge(int _1, int _2, int _3, int _4) : from(_1), to(_2), caps(_3), cost(_4){}
}es[maxm];
ZKW(){memset(head, -, sizeof(head));}
void setn(int _){n = _;}
void AddEdge(int u, int v, int w, int c)
{
es[m] = Edge(u, v, w, c); nx[m] = head[u]; head[u] = m++;
es[m] = Edge(v, u, , -c); nx[m] = head[v]; head[v] = m++;
}
bool BFS()
{
for(int i = ;i <= n;i++)dis[i] = -oo;
dis[t] = ;inq[t] = ;q.push(t);
while(!q.empty())
{
int now = q.front();q.pop();
for(int i = head[now]; i != -; i = nx[i])
{
Edge& e = es[i^];
if(e.caps && dis[e.from] < dis[now] + e.cost)
{
dis[e.from] = dis[now] + e.cost;
if(!inq[e.from])
{
inq[e.from] = ;
q.push(e.from);
}
}
}
inq[now] = ;
}
if(dis[s] > ){cost = dis[s];return ;}
return ;
}
int DFS(int u, int a)
{
if(u == t || !a)return ans += cost * a, a;
if(vis[u])return ; vis[u] = ;
int flow = , f;
for(int i = head[u]; i != -; i = nx[i])
{
Edge& e = es[i];
if(dis[e.to] == dis[u] - e.cost && (f = DFS(e.to, min(e.caps, a))))
{
e.caps -= f; es[i^].caps += f;
a -= f; flow += f;
if(!a)return flow;
}
}
return flow;
}
int MaxCostFlow(int _s, int _t, int tms)
{
s = _s, t = _t;
int flow = , f;
for(int i = ; i <= tms; i++) if(BFS()) {memset(vis, , sizeof(vis)); flow += DFS(s, oo);}
return flow;
}
} sol;
int n, m, k, s, t, ans;
int mat[][],mem[][][],dfn,b[maxn];
inline int pos(int x, int y, int type)
{
return n * n * (type - ) + (x - ) * n + y;
}
int main()
{
n = read(), m = read(), k = read();
for(int i = ; i <= n; i++)
for(int j = ; j <= n; j++) mat[i][j] = read();
s = , t = n * n * + ;
sol.setn(t + );
for(int i = ; i <= k; i++)
{
int x = read(), y = read();
b[pos(x, y, )] = ;
} for(int i = ; i <= n; i++)
for(int j = ; j <= n; j++)
{
ans += mat[i][j];
if(b[pos(i, j, )])continue;
if((i + j) & )
sol.AddEdge(pos(i, j, ), pos(i, j, ), , mat[i][j]);
else
{
if(i & )
{
sol.AddEdge(s, pos(i, j, ), , );
if(i > ) sol.AddEdge(pos(i, j, ), pos(i - , j, ), , );
if(j > ) sol.AddEdge(pos(i, j, ), pos(i, j - , ), , );
if(i < n) sol.AddEdge(pos(i, j, ), pos(i + , j, ), , );
if(j < n) sol.AddEdge(pos(i, j, ), pos(i, j + , ), , );
}
else
{
sol.AddEdge(pos(i, j, ), t, , );
if(i > ) sol.AddEdge(pos(i - , j, ),pos(i, j, ), , );
if(j > ) sol.AddEdge(pos(i, j - , ),pos(i, j, ), , );
if(i < n) sol.AddEdge(pos(i + , j, ), pos(i, j, ), , );
if(j < n) sol.AddEdge(pos(i, j + , ), pos(i, j, ), , );
}
}
} sol.MaxCostFlow(s, t, m);
cout << ans - sol.ans << endl;
}

不知道为什么 在限制增广次数的时候 ZKW 的多路增广是错的

bzoj 5403 Marshland的更多相关文章

  1. BZOJ 2127: happiness [最小割]

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

  2. BZOJ 3275: Number

    3275: Number Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 874  Solved: 371[Submit][Status][Discus ...

  3. BZOJ 2879: [Noi2012]美食节

    2879: [Noi2012]美食节 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1834  Solved: 969[Submit][Status] ...

  4. bzoj 4610 Ceiling Functi

    bzoj 4610 Ceiling Functi Description bzoj上的描述有问题 给出\(n\)个长度为\(k\)的数列,将每个数列构成一个二叉搜索树,问有多少颗形态不同的树. Inp ...

  5. BZOJ 题目整理

    bzoj 500题纪念 总结一发题目吧,挑几道题整理一下,(方便拖板子) 1039:每条线段与前一条线段之间的长度的比例和夹角不会因平移.旋转.放缩而改变,所以将每条轨迹改为比例和夹角的序列,复制一份 ...

  6. 【sdoi2013】森林 BZOJ 3123

    Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数.第三行包含N个非负整数 ...

  7. 【清华集训】楼房重建 BZOJ 2957

    Description 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题,我们考虑这些 ...

  8. 【splay】文艺平衡树 BZOJ 3223

    Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3  ...

  9. bzoj 刷水

    bzoj 3856: Monster 虽然是sb题,,但是要注意h可能<=a,,,开始忘记判了WA得很开心. #include <iostream> #include <cst ...

随机推荐

  1. SQLServer导入Excel,复杂操作

    导入Excel 先导入的时候报错了, 提示未在本地计算机上注册"Microsoft.ACE.Oledb.12.0"提供程序.(System.Data),去网址下个软件安装就搞定了, ...

  2. bacula 备份恢复

    一.数据恢复: 在bacula服务器执行: /opt/bacula/etc/ bconsole #进入交互窗口 *restore #输入restore恢复命令 Automatically select ...

  3. Unicode与UTF-8/UTF-16/UTF-32的区别

    Unicode的最初目标,是用1个16位的编码来为超过65000字符提供映射.但这还不够,它不能覆盖全部历史上的文字,也不能解决传输的问题 (implantation head-ache's),尤其在 ...

  4. SpringBoot整合Redis集群

    一.环境搭建 Redis集群环境搭建:https://www.cnblogs.com/zwcry/p/9174233.html 二.Spring整合Redis集群 1.pom.xml <proj ...

  5. Linux基本命令 关机命令

    linux下常用的关机命令有:shutdown.halt.poweroff.init:重启命令有:reboot.下面本文就主要介绍一些常用的关机命令以及各种关机命令之间的区别和具体用法. 首先来看一下 ...

  6. 验证——正则<37>

    1,郵箱合法性驗證 /* * 郵箱合法性驗證 * @method matchTel * @papram{string} str,電子郵箱 * @return{boolean} * */ functio ...

  7. 23种设计模式UML表示形式

    一.概况:       类关系表示:   说明:           二.创建型 1.Factory Method 意图: 定义一个用于创建对象的接口,让子类决定实例化哪一个类.Factory Met ...

  8. Android 下的usb框架及功能点【转】

    本文转载自:https://blog.csdn.net/tianruxishui/article/details/37902959 有关USB android框架的链接 http://blog.sin ...

  9. Centos7 关闭Ipv6

  10. 【codevs1002】搭桥(prim)

    题目描述: 这是道题题意有点迷(或者是我语文不好),但其实实际上求的就是图中连通块的个数,然后在连通块与连通块之间连边建图跑最小生成树.但是……这个图可能是不连通的……求桥的数量和总长 于是我立刻想到 ...