[SRM577]BoardPainting
题意:一个全白的网格,你要将一些格子涂黑,每次只能选一行或一列中的连续白格涂黑,问最小操作次数
先假装我们一次涂一个联通块,那么答案就是联通块个数,然后在这个基础上增加一些代价让方案变得合法
考虑这样建图:对两个水平相邻的要涂黑的格子$x,y$,建新点$u$,连$(S,u,1),(u,x,\infty),(u,y,\infty)$,对两个竖直相邻的要涂黑的格子$x,y$,建新点$v$,连$(x,v,\infty),(y,v,\infty),(v,T,1)$
如果存在一条$S\rightarrow u\rightarrow x\rightarrow v\rightarrow T$的路径,说明当前的涂色方案并不合法(染色转弯),于是我们需要把这条路径割掉,代表从联通块中分出一部分让答案变得合法,所以答案还要加上这个图的最小割
#include<stdio.h> #include<string.h> #include<algorithm> #include<vector> #include<string> using namespace std; const int inf=2147483647; int h[7510],nex[40010],to[40010],cap[40010],M=1,S,T; void ins(int a,int b,int c){ M++; to[M]=b; cap[M]=c; nex[M]=h[a]; h[a]=M; } void add(int a,int b,int c){ ins(a,b,c); ins(b,a,0); } int dis[7510],q[7510]; bool bfs(){ int head,tail,x,i; memset(dis,-1,sizeof(dis)); head=tail=1; q[1]=S; dis[S]=0; while(head<=tail){ x=q[head++]; for(i=h[x];i;i=nex[i]){ if(cap[i]&&dis[to[i]]==-1){ dis[to[i]]=dis[x]+1; if(to[i]==T)return 1; q[++tail]=to[i]; } } } return 0; } int cur[7510]; int dfs(int x,int flow){ if(x==T)return flow; int us=0,i,t; for(i=cur[x];i&&flow;i=nex[i]){ if(cap[i]&&dis[to[i]]==dis[x]+1){ t=dfs(to[i],min(flow,cap[i])); cap[i]-=t; cap[i^1]+=t; us+=t; flow-=t; if(cap[i])cur[x]=i; } } if(us==0)dis[x]=-1; return us; } int dicnic(){ int ans=0; while(bfs()){ memcpy(cur,h,sizeof(h)); ans+=dfs(S,inf); } return ans; } int id[60][60]; class BoardPainting{ public: int minimalSteps(vector<string>mp){ int n,m,i,j,N,ans; n=mp.size(); m=mp[0].length(); N=2; S=1; T=2; ans=0; for(i=0;i<n;i++){ for(j=0;j<m;j++){ if(mp[i][j]=='#'){ id[i][j]=++N; ans++; } } } for(i=0;i<n;i++){ for(j=0;j<m;j++){ if(id[i][j]){ if(id[i+1][j]){ ans--; N++; add(id[i][j],N,inf); add(id[i+1][j],N,inf); add(N,T,1); } if(id[i][j+1]){ ans--; N++; add(S,N,1); add(N,id[i][j],inf); add(N,id[i][j+1],inf); } } } } return ans+dicnic(); } }; /* int main(){ BoardPainting cl; vector<string>v; char s[110]; for(scanf("%s",s);s[0]!='E';scanf("%s",s))v.push_back(s); printf("%d",cl.minimalSteps(v)); } */
[SRM577]BoardPainting的更多相关文章
- Topcoder口胡记 SRM 562 Div 1 ~ SRM 599 Div 1
据说做TC题有助于提高知识水平? :) 传送门:https://284914869.github.io/AEoj/index.html 转载请注明链接:http://www.cnblogs.com/B ...
随机推荐
- CEdit使用(Edit Control控件)
CEdit使用(Edit Control控件) 编辑框只读 属性 Read Only等于 True,就有了只读效果 密码框 属性 Password 等于 True,就有了密码效果 获取值/赋予值 Up ...
- CentOS配置SSH无密码
210-211/212/213的集群中,新增215节点,操作:1.将210的id_rsa.pub拷贝到215中:scp ~/.ssh/id_rsa.pub 192.168.0.215@host:/ho ...
- Ubuntu 下更简单的防火墙 Uncomplicated Firewall
一看名字就十分的明确“不复杂防火墙”没错,它就是 ufw,在 Ubuntu 操作系统当中已经内置,使用它可以简单快速的操作防火墙的功能,比如开关端口,访问 IP,限制连接等等等等.它与一系列 Linu ...
- 深入理解node.js异步编程:基础篇
###[本文是基础内容,大神请绕道,才疏学浅,难免纰漏,请各位轻喷] ##1. 概述 目前开源社区最火热的技术当属Node.js莫属了,作为使用Javascript为主要开发语言的服务器端编程技术和平 ...
- 自动化运维之cobbler安装centos7.3
自动化运维之cobbler安装centos7.3 一.cobbler简介和服务 Cobbler是一款自动化操作系统安装的实现,与PXE安装系统的区别就是可以同时部署多个版本的系统,而PXE只能选择一种 ...
- ADC自动转接功能Lua实现
一.背景介绍: 虽然使用Mod_fifo和mod_callcenter可以做呼叫中心的应用,但在实现应用中,这两个模块很难客制化需求,再此我用Lua实现了5路客服(1000-1004),一个呼叫中心号 ...
- Jquery属性选择器(同时匹配多个条件,与或非)(附样例)
1. 前言 为了处理除了两项不符合条件外的选择,需要用到jquery选择器的多个条件匹配来处理,然后整理了一下相关的与或非的条件及其组合. 作为笔记记录. 2. 代码 <!DOCTYPE htm ...
- Java中的钩子方法
钩子方法是啥 钩子顾名思义就是用来挂东西的.那么要挂东西必须有个被挂的东西,要不就是铁环.要不就是墙的边沿.所以要能挂住东西必须要有个被勾住的铁环,要一个钩子.那么在java中也是同样的原理,你首先需 ...
- poj2481树状数组解二维偏序
按区间r降序排列,r相同按照l升序排列,两个区间相同时特判一下即可 /* 给定n个闭区间[l,r],如果对区间[li,ri],[lj,rj]来说, 有区间j严格包含(两个边界不能同时重合)在区间i内, ...
- 获取修改CSS
获取CSS使用方法css("CSS属性名称"), 示例css("color") 设置CSS使用方法css("CSS属性名称","属 ...