Problem Description
欢迎来到珠海!

由于土地资源越来越紧张,使得许多海滨城市都只能依靠填海来扩展市区以求发展。作为Z市的决策人,在仔细观察了Z市地图之后,你准备通过填充某些海域来扩展Z市的海岸线到最长,来吸引更多的游客前来旅游度假。为了简化问题,假设地图为一个N*M的格子,其中一些是陆地,一些是可以填充的浅海域,一些是不可填充的深海域。这里定义海岸线的长度为一个联通块陆地(可能包含浅海域填充变为的陆地)的边缘长度,两个格子至少有一个公共边,则视为联通。

值得注意的是,这里Z市的陆地区域可以是不联通的,并且整个地图都处在海洋之中,也就是说,Z市是由一些孤岛组成的,比如像,夏威夷?

你的任务是,填充某些浅海域,使得所有岛屿的海岸线之和最长。

Input
输入第一行为T,表示有T组测试数据。
每组数据以两个整数N和M开始,表示地图的规模。接下来的N行,每一行包含一个长度为M的字符串,表示地图,‘.’表示陆地,’E’表示浅海域,’D’表示深海域。

[Technical Specification]

1. 1 <= T <= 100
2. 1 <= N, M <= 47

Output
对每组数据,先输出为第几组数据,然后输出最长的海岸线长度。
Sample Input
3
2 2
EE
EE
3 3
EEE
.E.
EEE
3 3
EEE
DED
EEE
Sample Output
Case 1: 8
Case 2: 16
Case 3: 20

Hint

对于第三组样例,一种可行方案是:

.E.
D.D
.E.

这样5个孤立小岛的海岸线总长为4 * 5 = 20。

 
 
 
 
【分析】
  网络流构图。
  最小割定理:最小割等于最大流。
  

因为E有两个选择D或者.   其实就暗含了最小割的模型。 最小割的话,就是一部分分到源点一侧,一部分分到汇点一侧。

如果把源点分在一起当成是.   和汇点分在一起当成是D.  那么建图的时候,相邻的建流量为1的边。 如果这个点本来是. 那个连汇点是INF,本来是D的,连源点是INF。

如果是这种建图的话,最小割求出来的最小周长。

我们需要的最大周长。

稍微转化下。 我们希望相邻格子不同的最多,其实就是要相邻格子相同的最少。

所以用最小割来求相邻格子相同的最小值,然后总相邻数减掉这个就是答案了。

建图方法就是一开始进行奇偶染色。相当于对于点(x,y)

如果(x+y)%2 == 0 那么当成这个格子是 . 的,和源点分在一起。

如果(x+y)%2 == 1 那么当成这个格子是 D 的,和汇点分在一起。

相邻两点都建边。

这样建图的话,如果在源点一侧的跑到了汇点一侧,那么就相当于这个点从.变到D, 自然相同的数量要减少了、

汇点一侧的跑到了源点一侧,那么就相当于这个点从D变成了.

建图的时候,如果(x+y)%2==0 && 这个点本来就是D  或者 (x+y)%2 == 1 && 这个点本来就是.     那么这个点必须和汇点在一起,就把这个点和源点连INF的边。 相反情况类似处理。

这样建图出来的最小割,一定就是相邻格子是同一类的最小数量。总相邻减掉这个值就是答案了。

 
 
  即如图所示:
 
  对于右边绿色的图的情况的(1,1)点和(1,2)点连边如图所示。(蓝色为边的编号,橙色为流量)
  上面棕色点为(1,1) 下面棕色点为(1,2)
    割边1表示点(1,1)为陆,割边2表示点(1,1)为海
    割边4表示点(1,2)为海,割边5表示点(1,2)为陆
  因为有双向边3,所以当两点同为陆或者海,必须把3号边也割了(花费1),图才能分割开。
  一开始假设所有有可能的(即不确定的)都是海岸线,建图跑最小割即可。
  注意相邻两点表示陆海的时候要反过来。
 
  网络流之前打的模版有点慢,导致我一直TLE,这样做会快一点:
 
AC代码如下:
 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define Maxn 4010
#define Maxm 4010*4
#define INF 0xfffffff char s[]; int map[][];
int dx[]={,-,,,},
dy[]={,,-,,};
int num[][];
int s1[][],s2[][]; struct node
{
int x,y,f,o,next;
}t[Maxm*];int len; int st,ed;
int dis[Maxn],first[Maxn]; int mymin(int x,int y) {return x<y?x:y;} void ins(int x,int y,int f)
{
if(f==) return;
t[++len].x=x;t[len].y=y;t[len].f=f;
t[len].next=first[x];first[x]=len;t[len].o=len+;
t[++len].x=y;t[len].y=x;t[len].f=;
t[len].next=first[y];first[y]=len;t[len].o=len-;
} queue<int > q;
bool bfs()
{
while(!q.empty()) q.pop();
memset(dis,-,sizeof(dis));
dis[st]=;q.push(st);
while(!q.empty())
{
int x=q.front();q.pop();
for(int i=first[x];i;i=t[i].next) if(t[i].f>)
{
int y=t[i].y;
if(dis[y]==-)
{
dis[y]=dis[x]+;
q.push(y);
}
}
}
if(dis[ed]!=-) return ;
return ;
} int ffind(int x,int mmin)
{
if(x==ed) return mmin;
int r=;
for(int i=first[x];i;i=t[i].next) if(dis[t[i].y]==dis[x]+ && t[i].f>)
{
int y=t[i].y,a=mymin(t[i].f,mmin-r);
a=ffind(y,a);r+=a;
t[i].f-=a;
t[t[i].o].f+=a;
}
if(r==) dis[x]=-;
return r;
} int min_cut()
{
int a,ans=;
while(bfs()) ans+=ffind(st,INF);
return ans;
} int main()
{
int T,kase=,ans;
scanf("%d",&T);
while(T--)
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
{
scanf("%s",s);
for(int j=;j<m;j++)
{
if(s[j]=='E') map[i][j+]=;
else if(s[j]=='.') map[i][j+]=;
else map[i][j+]=;
}
} int ans=*n*m+n+m;
for(int i=;i<=m+;i++) map[][i]=,map[n+][i]=;
for(int i=;i<=n+;i++) map[i][]=,map[i][m+]=; memset(s1,,sizeof(s1));
memset(s2,,sizeof(s2));
for(int i=;i<=n;i++)
for(int j=;j<=m;j++) if(map[i][j]!=)
{
int now=i*(m+)+j;
for(int k=;k<=;k++)
{
int nx=i+dx[k],ny=j+dy[k];
if(map[i][j]==) s1[nx][ny]++;
if(map[i][j]==) s2[nx][ny]++;
if((nx==||ny==||nx==n+||ny==m+)&&map[i][j]==) ans--;
else if(map[nx][ny]!=&&map[nx][ny]==map[i][j]&&k<=) ans--;
}
}
for(int i=;i<=m;i++) s2[][i]++,s2[n][i]++;
for(int i=;i<=n;i++) s2[i][]++,s2[i][m]++;
memset(first,,sizeof(first));
len=;int cnt=;
st=,ed=;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++) if(map[i][j]==)
{
int now=++cnt;num[i][j]=cnt;
if((i+j)%==) {ins(now,ed,s2[i][j]);ins(st,now,s1[i][j]);}
else {ins(now,ed,s1[i][j]);ins(st,now,s2[i][j]);}
for(int k=;k<=;k++)
{
int nx=i+dx[k],ny=j+dy[k];
if(nx<||nx>n||ny<||ny>m) continue;
if(map[nx][ny]!=) continue;
int d=num[nx][ny];
ins(now,d,);ins(d,now,);
}
}
ans-=min_cut();
printf("Case %d: %d\n",++kase,ans);
}
return ;
}

[HDU4859]

2016-05-17 16:42:42

【HDU4859】 海岸线(网络流-最小割)的更多相关文章

  1. HDU4859 海岸线(最小割)

    题目大概就是说一个n*m的地图,地图上每一块是陆地或浅海域或深海域,可以填充若干个浅海域使其变为陆地,问能得到的最长的陆地海岸线是多少. 也是很有意思的一道题. 一开始想歪了,想着,不考虑海岸线重合的 ...

  2. 【题解】 bzoj3894: 文理分科 (网络流/最小割)

    bzoj3894,懒得复制题面,戳我戳我 Solution: 首先这是一个网络流,应该还比较好想,主要就是考虑建图了. 我们来分析下题面,因为一个人要么选文科要么选理科,相当于两条流里面割掉一条(怎么 ...

  3. 【bzoj3774】最优选择 网络流最小割

    题目描述 小N手上有一个N*M的方格图,控制某一个点要付出Aij的代价,然后某个点如果被控制了,或者他周围的所有点(上下左右)都被控制了,那么他就算是被选择了的.一个点如果被选择了,那么可以得到Bij ...

  4. 【bzoj1143】[CTSC2008]祭祀river Floyd+网络流最小割

    题目描述 在遥远的东方,有一个神秘的民族,自称Y族.他们世代居住在水面上,奉龙王为神.每逢重大庆典, Y族都会在水面上举办盛大的祭祀活动.我们可以把Y族居住地水系看成一个由岔口和河道组成的网络.每条河 ...

  5. 【bzoj1797】[Ahoi2009]Mincut 最小割 网络流最小割+Tarjan

    题目描述 给定一张图,对于每一条边询问:(1)是否存在割断该边的s-t最小割 (2)是否所有s-t最小割都割断该边 输入 第一行有4个正整数,依次为N,M,s和t.第2行到第(M+1)行每行3个正 整 ...

  6. 【bzoj1976】[BeiJing2010组队]能量魔方 Cube 网络流最小割

    题目描述 一个n*n*n的立方体,每个位置为0或1.有些位置已经确定,还有一些需要待填入.问最后可以得到的 相邻且填入的数不同的点对 的数目最大. 输入 第一行包含一个数N,表示魔方的大小. 接下来 ...

  7. 【bzoj4177】Mike的农场 网络流最小割

    题目描述 Mike有一个农场,这个农场n个牲畜围栏,现在他想在每个牲畜围栏中养一只动物,每只动物可以是牛或羊,并且每个牲畜围栏中的饲养条件都不同,其中第i个牲畜围栏中的动物长大后,每只牛可以卖a[i] ...

  8. 【bzoj3438】小M的作物 网络流最小割

    原文地址:http://www.cnblogs.com/GXZlegend/p/6801522.html 题目描述 小M在MC里开辟了两块巨大的耕地A和B(你可以认为容量是无穷),现在,小P有n中作物 ...

  9. 【bzoj3144】[Hnoi2013]切糕 网络流最小割

    题目描述 输入 第一行是三个正整数P,Q,R,表示切糕的长P. 宽Q.高R.第二行有一个非负整数D,表示光滑性要求.接下来是R个P行Q列的矩阵,第z个 矩阵的第x行第y列是v(x,y,z) (1≤x≤ ...

  10. 【bzoj3894】文理分科 网络流最小割

    原文地址:http://www.cnblogs.com/GXZlegend 题目描述 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠结过) 小P所在的班级要进行文理分科.他的班级可以用 ...

随机推荐

  1. AOP 的利器:ASM 3.0 介绍

    引言 什么是 ASM ? ASM 是一个 Java 字节码操控框架.它能被用来动态生成类或者增强既有类的功能.ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态 ...

  2. PHP5常量

    用函数 define()设置常量 define函数有3个参数 1.必选,常量的名称,标识符 2.必选,常量的值 3.可选,默认不设置,常量名称大小写敏感.如果设置true,常量名称不区分大小写! 下面 ...

  3. readonly时禁用删除键,readonly按删除键后页面后退解决方案

    readonly时禁用删除键, readonly按删除键后页面后退解决方案 >>>>>>>>>>>>>>>&g ...

  4. CentOS&nbsp;6.4&nbsp;图文安装教…

    点评:CentOS 6.4是最新的出的系统,这里分享下安装教程,有些设置大部分教程没出现过,特分享下,方便需要的朋友 CentOS 6.4 下载地址: http://www.jb51.net/soft ...

  5. XML--小结①

  6. c#基础-----数据类型,转义字符,引用类型,类型转换

    数据类型,转义字符,引用类型,类型转换 百度一下

  7. 分享一个在PearOS里面的plank的配置文件

    plank的配置文件的路径是/home/pear/.config/plank/dock1/settings #This file auto-generated by Plank. #2013-09-0 ...

  8. Lucene5.x 中文 同义词

    查询好好多资料,英文同义词好好的,中文就不行,多谢网友支持,拼接了好多代码,然后修改了一些,不足之处,多谢指正. 直接上代码吧,在代码中了解怎么分词的最好 1,创建分词引擎 public interf ...

  9. npm 好用工具 for 前端

    1. caniuse npm install -g caniuse-cmd

  10. [转]操作xml,将xml数据显示到treeview的C#代码

    XmlDocument xml = new XmlDocument(); private void Form1_Load(object sender, EventArgs e) { CreateXML ...