http://acm.hdu.edu.cn/showproblem.php?pid=4859

题目大意:

  在一个矩形周围都是海,这个矩形中有陆地,深海和浅海。浅海是可以填成陆地的。

  求最多有多少条方格线满足两侧分别是海洋和陆地

这道题很神

首先考虑一下,什么情况下能够对答案做出贡献

就是相邻的两块不一样的时候

这样我们可以建立最小割模型,可是都说是最小割了

无法求出最大的不相同的东西

所以我们考虑转化,用总的配对数目 - 最小的相同的对数

至于最小的相同的对数怎么算呢?

我们考虑这样的构造方法:

 把整个棋盘黑白染色,我们想要所有的黑格子都是陆地,所有的白格子都是海洋

 但是天不尽人意

 输入数据肯定不会给你做出这种东西,所以会出现各种各样的不符的格子

 所以我们把所有符合的格子和不符的格子拿开

 把所有的与其所在的集合相符的格子放到一个集合中(记为S1)

 把所有的与其所在的集合不相符的格子放到另一个集合中(记为S2)

 把剩下的没有被分到任何集合的格子,也就是所有的E格,放到另一个集合中(记为S3)

 然后我们在所有相邻且所在集合不同(S1,S2,S3)点之间连上双向边

 这时图中存在的任意一条从S -> T的可行流都一定经过S1,S2集合中两个形式相同的格子

 这时候还有可能经过若干S3中的点

 那么这时候就代表我们让这些S3中的点和S1,S2中我们选择的点的形式相同

 这就是最小的相同对数了

 所以ans = tot - dinic()其中tot = (n-1)*m + (m-1)*n

 做完了题了我们定义一下每一条边的含义:

  一条边一定是条双向边

  这条边代表的含义就是这条边连接的两个点必须相同才有可能对答案做出贡献

  而我们知道,一条边连接的两个格子一定在最初的黑白染色中属于不同的颜色

  如果他们颜色相同的话,一定不会被一起分到s1或s2集合中

  并且一定会被分散到S1和S2集合中

  所以我们不能连接相同集合中的边,却能连接不同集合中的边

但是连接的话从数值上来说是不变的,可是本人认为意义上解释不通

网上的其他题解都是没有关心是否在同一个集合内部,都进行了连边

不过本人太弱,无论如何都想不通集合内部的边的意义,所以本人认为那条边不应该存在,是没有意义的。

如果真的是本苣太弱了,还请各位dalao高台贵手。。

Code : 删去了集合内部的边,依然AC

 #include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
inline void read(int &x){
x=;char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=*x+ch-'',ch=getchar(),ch>'!');if(flag) x=-x;
}
inline int cat_max(const int &a,const int &b){return a>b ? a:b;}
inline int cat_min(const int &a,const int &b){return a<b ? a:b;}
const int maxn = ;
const int maxnode = ;
const int maxedge = ;
const int inf = 0x3f3f3f3f;
struct Edge{
int to,next,cap;
}G[maxedge<<];
int head[maxnode],cnt=;
void add(int u,int v,int c){
G[++cnt].to = v;
G[cnt].next = head[u];
G[cnt].cap = c;
head[u] = cnt;
}
void insert(int u,int v,int c){
add(u,v,c);add(v,u,);
}
int dis[maxnode],q[maxnode],l,r;
int S,T,cur[maxnode];
#define v G[i].to
bool bfs(){
memset(dis,-,sizeof dis);
dis[S] = ;l = ;r = -;
q[++r] = S;
while(l <= r){
int u = q[l++];
for(int i = head[u];i;i=G[i].next){
if(dis[v] == - && G[i].cap){
dis[v] = dis[u] + ;
q[++r] = v;
}
}
}return dis[T] != -;
}
int dfs(int u,int f){
if(u == T || f == ) return f;
int ret = ;
for(int &i = cur[u];i;i=G[i].next){
if(dis[v] == dis[u] + ){
int x = dfs(v,cat_min(G[i].cap,f));
ret += x;f -= x;
G[i].cap -= x;G[i^].cap += x;
if(f == ) break;
}
}if(ret == ) dis[u] = -;
return ret;
}
#undef v
inline int dinic(){
int ret = ;
while(bfs()){
memcpy(cur,head,sizeof head);
ret += dfs(S,inf);
}return ret;
}
int tag[maxnode];
inline void init(){
memset(head,,sizeof head);
memset(tag,,sizeof tag);
cnt = ;S = maxnode - ;T = S+;
}
char map[maxn][maxn],ch;
#define f(x,y) ((x-1)*m+y)
int dx[] = {,,,,-};
int dy[] = {,,-,,};
int main(){
int tim;read(tim);
for(int Case = ;Case <= tim;++Case){
init();
int n,m;read(n);read(m);
for(int i=;i<=n+;++i) map[i][] = map[i][m+] = 'D';
for(int i=;i<=m+;++i) map[][i] = map[n+][i] = 'D';
for(int i=;i<=n+;++i){
for(int j=;j<=m+;++j){
while(ch=getchar(),ch<'!');
map[i][j] = ch;
}
}n += ;m += ;
for(int i=;i<=n;++i){
for(int j=;j<=m;++j){
if((i+j)&){
if(map[i][j] == '.') insert(S,f(i,j),inf),tag[f(i,j)] = ;
if(map[i][j] == 'D') insert(f(i,j),T,inf),tag[f(i,j)] = ;
}else{
if(map[i][j] == 'D') insert(S,f(i,j),inf),tag[f(i,j)] = ;
if(map[i][j] == '.') insert(f(i,j),T,inf),tag[f(i,j)] = ;
}
for(int k=;k<=;++k){
int nx = i + dx[k];
int ny = j + dy[k];
if(nx < || ny < || nx > n || ny > m) continue;
if(tag[f(i,j)] == || tag[f(nx,ny)] == ) insert(f(i,j),f(nx,ny),);
else if(tag[f(i,j)] != tag[f(nx,ny)]) insert(f(i,j),f(nx,ny),);
}
}
}
int ans = (*n*m) - (n+m) - dinic();
printf("Case %d: %d\n",Case,ans);
}
getchar();getchar();
return ;
}

hdu 4859 海岸线 Bestcoder Round 1的更多相关文章

  1. hdu 5636 搜索 BestCoder Round #74 (div.2)

    Shortest Path  Accepts: 40  Submissions: 610  Time Limit: 4000/2000 MS (Java/Others)  Memory Limit: ...

  2. HDU 5904 - LCIS (BestCoder Round #87)

    HDU 5904 - LCIS [ DP ]    BestCoder Round #87 题意: 给定两个序列,求它们的最长公共递增子序列的长度, 并且这个子序列的值是连续的 分析: 状态转移方程式 ...

  3. hdu 4859 海岸线 最小割

    海岸线 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=4859 Description 欢迎来到珠海! 由于土地资源越来越紧张,使得许多海滨城市都只能 ...

  4. HDU 4859 海岸线(最小割+最大独立点权变形)

    http://acm.hdu.edu.cn/showproblem.php?pid=4859 题意: 欢迎来到珠海!由于土地资源越来越紧张,使得许多海滨城市都只能依靠填海来扩展市区以求发展.作为Z市的 ...

  5. HDU 4859 海岸线(最大流最小割)

    难得的中文题,就不翻译了. 输入第一行为T,表示有T组测试数据.每组数据以两个整数N和M开始,表示地图的规模.接下来的N行,每一行包含一个长度为M的字符串,表示地图,‘.’表示陆地,’E’表示浅海域, ...

  6. HDU 5778 abs (BestCoder Round #85 C)素数筛+暴力

    分析:y是一个无平方因子数的平方,所以可以从sqrt(x)向上向下枚举找到第一个无平方因子比较大小 大家可能觉得这样找过去暴力,但实际上无平方因子的分布式非常密集的,相关题目,可以参考 CDOJ:无平 ...

  7. HDU 5776 sum (BestCoder Round #85 A) 简单前缀判断+水题

    分析:就是判断简单的前缀有没有相同,注意下自身是m的倍数,以及vis[0]=true; #include <cstdio> #include <cstdlib> #includ ...

  8. hdu 5101 Select(Bestcoder Round #17)

    Select                                                    Time Limit: 4000/2000 MS (Java/Others)     ...

  9. HDU 5908 Abelian Period (BestCoder Round #88 模拟+暴力)

    HDU 5908 Abelian Period (BestCoder Round #88 模拟+暴力) 题目链接http://acm.hdu.edu.cn/showproblem.php?pid=59 ...

随机推荐

  1. LAMP布署笔记

    源代码软件的优点:     获得最新版,能及时修复bug:     能自行修改和定制: 源代码打包形式:     .tar.gz和.tar.bz2格式居多: 完整性校验:     md5sum校验工具 ...

  2. jQuery全选、全不选、反选

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <script sr ...

  3. Unity、c#中的拓展方法讲解

    很早以前看过这个东西,但是没有真正的用到过,希望之后会用到上面的方法, 大概的意思是这样的c#中尤其在用Unity的时候,已有的框架提供给我们一些固定的方法,但是有时我们想对这些方法进行修改, 这时我 ...

  4. Linux 6.5(oracle 11.2.0.4)单实例ASM安装

    Linux 6.5(oracle 11.2.0.4) 1.解析主机.配置网络等 /etc/hosts /etc/sysconfig/network /etc/init.d/NetworkManager ...

  5. SQL语句中的where 1=1 和0=1

    摘自:http://blog.sina.com.cn/s/blog_afe616ab0101camd.html SQL where 1=1 和0=1的作用 where 1=1; 这个条件始终为True ...

  6. 从零自学Hadoop系列索引

    本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作. 文章是哥(mephisto)写的,SourceLink 从零自学Hadoop(01):认识Hadoop ...

  7. web工程常用路径的获取方法

    此文章是基于 搭建SpringMVC+Spring+Hibernate平台 一. 利用 Spring 取得web工程根路径 1. web.xml 中添加如下: <context-param> ...

  8. js入门学习~ 运动应用小例

    要实现的效果如下: 鼠标移入各个小方块,实现对应的效果(变宽,变高,移入透明,移出恢复)~~ (且各运动相互之前不干扰)  主要是练习多个物体的运动框架~~ --------------------- ...

  9. swt shell设置窗口位于屏幕中间

    /**     * 设置窗口位于屏幕中间     * @param shell 要调整位置的窗口对象     */    public static void center(Shell shell)  ...

  10. [No000090]C#捕获控制台(console)关闭事件及响应cmd快捷键

    捕获控制台(console)关闭事件: 1.Ctrl+C信号: 2.Ctrl+Break信号: 3.用户系统关闭Console时: 4.用户退出系统时: 5.系统将要关闭时: using System ...