https://www.zybuluo.com/ysner/note/1240792

题面

戳我

解析

这种用来拼接的奇形怪状的东西,要不就是轮廓线\(DP\),要不就是网络流。

为了表示奇数点(即\((x+y)\%2=1\))的危险值,把该点拆为两个点,连一条边长为该点危险值相反数的边(两点分别称为起点和终点)。

鉴于一根柱子跨越\(3\)个格子,其中一点为奇数点,另外两个点都是偶数点,不能区分。

于是也要把偶数点分为两类(不用拆点)。一类连源点,一类连汇点。连汇点的一类连奇数点的起点,另一类连终点。(让源点出发能到汇点就成)

然后思考如何表示柱子。

如果强行给柱子规定方向,则有\(8\)个方向。

表示出来,有两种情况,一是\(x\)轴方向出,\(y\)轴方向进;另一种是\(y\)轴方向进,\(x\)轴方向出。

于是两个奇数点分别反映一种情况,同时注意相邻的偶数点连奇数点中的起点、还是终点即可。

还要注意的是,最小费用最大流模板求出的是在最大流前提下的最小流,在后期,可能为了得到最大流而付出更多费用(在本题中就是为了放更多柱子而增加不稳定度)。在费用开始非负时(开始退流时)记得\(break\)。

唯一一种能让网络流TLE的方式就是cnt=0

// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#define re register
#define il inline
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define fp(i,a,b) for(re int i=a;i<=b;i++)
#define fq(i,a,b) for(re int i=a;i>=b;i--)
using namespace std;
const int mod=1e9+7,N=5e3+100;
struct Edge{int to,nxt,w,c;}e[N*10];
int n,m,k,s,sum,h[N],d[55][55],ans=0,dis[N],S,T,pe[N],pv[N],tot,cnt=1,g;
bool vis[N],ban[55][55];
il void add(re int u,re int v,re int w,re int c)
{
if(u==-1||v==-1) return ;
e[++cnt]=(Edge){v,h[u],w,c};h[u]=cnt;
e[++cnt]=(Edge){u,h[v],0,-c};h[v]=cnt;
}
queue<int>Q;
il ll gi()
{
re ll x=0,t=1;
re char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') t=-1,ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
return x*t;
}
il int id(re int x,re int y){return (x-1)*n+y;}
il int SPFA()
{
memset(dis,63,sizeof(dis));dis[S]=0;vis[S]=1;Q.push(S);
while(!Q.empty())
{
re int u=Q.front();Q.pop();
for(re int i=h[u];i+1;i=e[i].nxt)
{
re int v=e[i].to;//printf("!!!%d %d\n",u,v);
if(dis[v]>dis[u]+e[i].c&&e[i].w)
{
dis[v]=dis[u]+e[i].c;
pe[v]=i;pv[v]=u;
if(!vis[v]) vis[v]=1,Q.push(v);
}
}
vis[u]=0;
}
return dis[T]<dis[0];
}
int main()
{
//freopen("marshland.in","r",stdin);
//freopen("marshland.out","w",stdout);
memset(h,-1,sizeof(h));
n=gi();m=gi();k=gi();g=n*n;S=2*g+1;T=2*g+2;
fp(i,1,n)
fp(j,1,n)
d[i][j]=gi(),s+=d[i][j];
fp(i,1,k)
{
re int u=gi(),v=gi();
ban[u][v]=1;
}
fp(i,1,n)
fp(j,1,n)
{
if(ban[i][j]) continue;
if((i+j)%2) add(id(i,j),id(i,j)+g,1,-d[i][j]);
if((i+j)%2&&j%2==0)
{
if(i>1&&!ban[i-1][j]) add(id(i,j)+g,id(i-1,j),1,0);
if(i<n&&!ban[i+1][j]) add(id(i,j)+g,id(i+1,j),1,0);
if(j>1&&!ban[i][j-1]) add(id(i,j-1),id(i,j),1,0);
if(j<n&&!ban[i][j+1]) add(id(i,j+1),id(i,j),1,0);
}
if((i+j)%2&&j%2==1)
{
if(i>1&&!ban[i-1][j]) add(id(i-1,j),id(i,j),1,0);
if(i<n&&!ban[i+1][j]) add(id(i+1,j),id(i,j),1,0);
if(j>1&&!ban[i][j-1]) add(id(i,j)+g,id(i,j-1),1,0);
if(j<n&&!ban[i][j+1]) add(id(i,j)+g,id(i,j+1),1,0);
}
if((i+j)%2==0&&j%2==1) add(S,id(i,j),1,0);
if((i+j)%2==0&&j%2==0) add(id(i,j),T,1,0);
}
while(SPFA()&&m)
{
if(dis[T]>=0) break;
sum=2e9;
for(re int i=T;i!=S;i=pv[i])
sum=min(sum,e[pe[i]].w);m-=sum;//printf("%d\n",sum);
for(re int i=T;i!=S;i=pv[i])
e[pe[i]].w-=sum,e[pe[i]^1].w+=sum,ans+=sum*e[pe[i]].c;
}
printf("%d\n",s+ans);
fclose(stdin);
fclose(stdout);
return 0;
}

[luoguP4142]洞穴遇险的更多相关文章

  1. 【刷题】洛谷 P4142 洞穴遇险

    题目背景 ZRQ在洞穴中准备采集矿物的时候遇险了!洞穴要塌了! 题目来源:zhoutb2333 题目描述 整个洞穴是一个 \(N*N\) 的方格图,每个格子形如 \((X,Y),1 \le X,Y \ ...

  2. [Luogu] U18202 洞穴遇险

    https://www.luogu.org/problemnew/show/U18202 暴力搜索预期得分3030分左右. 状压预期得分7070分左右. 考虑费用流,将剩余不稳定度和最小转为消除不稳定 ...

  3. 二分图&网络流初步

    链接 : 最小割&网络流应用 EK太低级了,不用. 那么请看:#6068. 「2017 山东一轮集训 Day4」棋盘,不用EK你试试? dinic模板及部分变形应用见zzz大佬的博客:网络流学 ...

  4. 【BZOJ2049】 [Sdoi2008]Cave 洞穴勘测 LCT/并查集

    两种方法: 1.LCT 第一次LCT,只有link-cut和询问,无限T,到COGS上找了数据,发现splay里的父亲特判出错了(MD纸张),A了,好奇的删了反转T了.... #include < ...

  5. 【bzoj2049】[Sdoi2008]Cave 洞穴勘测 link-cut-tree

    2016-05-30  11:04:51 学习了link-cut-tree 二中神犇封禹的讲义感觉讲的超级清晰易懂啊(没有的可以q窝 算是模板吧 #include<bits/stdc++.h&g ...

  6. BZOJ-2049 Cave洞穴勘测 动态树Link-Cut-Tree (并查集骗分TAT)

    2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 10 Sec Memory Limit: 259 MB Submit: 5833 Solved: 2666 [Submit] ...

  7. BZOJ-2929 洞穴攀岩 最大流Dinic(傻逼题)

    竟然没有1A真羞耻...1分钟不到读完题,10分钟不到打完....MD没仔细看...WA了一遍,贱! 2929: [Poi1999]洞穴攀行 Time Limit: 1 Sec Memory Limi ...

  8. 【BZOJ】2929: [Poi1999]洞穴攀行(最大流)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2929 题意描述不清..搞得我wa了一发.. 应该是,有1和n的点的边容量都为1,其余随便... 然后 ...

  9. 【BZOJ】2049: [Sdoi2008]Cave 洞穴勘测(lct/并查集)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2049 bzoj挂了..在wikioi提交,,1A-写lct的速度越来越快了-都不用debug-- 新 ...

随机推荐

  1. Angular ZoneJS 原理

    Zone.js到底是如何工作的? 原文链接: blog.kwintenp.com 如果你阅读过关于Angular 2变化检测的资料,那么你很可能听说过zone.Zone是一个从Dart中引入的特性并被 ...

  2. gym101343J. Husam and the Broken Present 2 (状压DP)

    题意:给定n个串 每个串长度不超过100 找到一个新串 使得这n个串都是它的字串 输出这个新串的最小长度 题解:n是15 n的阶乘的复杂度肯定不行 就想到了2的15次方的复杂度 想到了状压但是不知道怎 ...

  3. fork 系统调用

    对自己知识储备的感觉就是过于肤浅,很多东西知其名后就不了了之 此系列博客将记录进程分析的学习过程,希望能够多些深度 提到进程,最容易的想到就是fork系统调用,比较好和快速的找到的fork的相关信息就 ...

  4. vue中路由

    关于每次点击链接都要刷新页面的问题众所周知,开发单页应用就是因为那丝般顺滑的体验效果,如果每次点击都会刷新页面… 出现这个的原因是因为使用了window.location来跳转,只需要使用使用rout ...

  5. 【18】AngularJS 包含

    AngularJS 包含 在 AngularJS 中,你可以在 HTML 中包含 HTML 文件. 在 HTML 中包含 HTML 文件 在 HTML 中,目前还不支持包含 HTML 文件的功能. 服 ...

  6. Ubuntu 16.04安装汇编编译器NASM

    NASM支持intel语法. 安装过程: 1.通过二进制包方式 下载: http://www.nasm.us/pub/nasm/releasebuilds/2.13/ 如果要下载其它版本可以把地址靠前 ...

  7. Unix stat

    Linux 下有stat命令,可以非常方便的得到一个文件的inode等信息.但是今天在Solaris下使用stat居然没有这个命令.不过没关系,我们可以自己写这个命令,比如: #include < ...

  8. fastjson将java list转为json字符串

    1.直接用fastjson的静态方法string JSON.toJSONString(list)方法就行,JSON.toJSONString(list)将java list转为json字符串. 2.t ...

  9. Android 自己定义控件实现刮刮卡效果 真的就仅仅是刮刮卡么

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/40162163 , 本文出自:[张鸿洋的博客] 非常久以前也过一个html5的刮刮 ...

  10. 用 Arduino Uno 给 Arduino Mini(Pro)烧录程序

    用 Arduino Uno 给 Arduino Mini(Pro)烧录程序 准备 Arduino Uno Arduino Mini(Pro) 杜邦线若干 接线 首先去掉 Arduino 上的芯片ATM ...