博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【HDU4859】 海岸线(网络流-最小割)
阅读量:5157 次
发布时间:2019-06-13

本文共 3393 字,大约阅读时间需要 11 分钟。

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代码如下:
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 using namespace std; 8 #define Maxn 4010 9 #define Maxm 4010*4 10 #define INF 0xfffffff 11 12 char s[60]; 13 14 int map[60][60]; 15 int dx[6]={ 0,-1,0,0,1}, 16 dy[6]={ 0,0,-1,1,0}; 17 int num[60][60]; 18 int s1[60][60],s2[60][60]; 19 20 struct node 21 { 22 int x,y,f,o,next; 23 }t[Maxm*2];int len; 24 25 int st,ed; 26 int dis[Maxn],first[Maxn]; 27 28 int mymin(int x,int y) { return x
q; 40 bool bfs() 41 { 42 while(!q.empty()) q.pop(); 43 memset(dis,-1,sizeof(dis)); 44 dis[st]=0;q.push(st); 45 while(!q.empty()) 46 { 47 int x=q.front();q.pop(); 48 for(int i=first[x];i;i=t[i].next) if(t[i].f>0) 49 { 50 int y=t[i].y; 51 if(dis[y]==-1) 52 { 53 dis[y]=dis[x]+1; 54 q.push(y); 55 } 56 } 57 } 58 if(dis[ed]!=-1) return 1; 59 return 0; 60 } 61 62 int ffind(int x,int mmin) 63 { 64 if(x==ed) return mmin; 65 int r=0; 66 for(int i=first[x];i;i=t[i].next) if(dis[t[i].y]==dis[x]+1 && t[i].f>0) 67 { 68 int y=t[i].y,a=mymin(t[i].f,mmin-r); 69 a=ffind(y,a);r+=a; 70 t[i].f-=a; 71 t[t[i].o].f+=a; 72 } 73 if(r==0) dis[x]=-1; 74 return r; 75 } 76 77 int min_cut() 78 { 79 int a,ans=0; 80 while(bfs()) ans+=ffind(st,INF); 81 return ans; 82 } 83 84 int main() 85 { 86 int T,kase=0,ans; 87 scanf("%d",&T); 88 while(T--) 89 { 90 int n,m; 91 scanf("%d%d",&n,&m); 92 for(int i=1;i<=n;i++) 93 { 94 scanf("%s",s); 95 for(int j=0;j
n||ny<1||ny>m) continue;137 if(map[nx][ny]!=0) continue;138 int d=num[nx][ny];139 ins(now,d,1);ins(d,now,1);140 }141 }142 ans-=min_cut();143 printf("Case %d: %d\n",++kase,ans);144 }145 return 0;146 }
[HDU4859]

 

2016-05-17 16:42:42

转载于:https://www.cnblogs.com/Konjakmoyu/p/5502241.html

你可能感兴趣的文章
NSPredicate的使用,超级强大
查看>>
自动分割mp3等音频视频文件的脚本
查看>>
判断字符串是否为空的注意事项
查看>>
布兰诗歌
查看>>
js编码
查看>>
Pycharm Error loading package list:Status: 403错误解决方法
查看>>
steps/train_sat.sh
查看>>
转:Linux设备树(Device Tree)机制
查看>>
iOS 组件化
查看>>
(转)Tomcat 8 安装和配置、优化
查看>>
(转)Linxu磁盘体系知识介绍及磁盘介绍
查看>>
tkinter布局
查看>>
命令ord
查看>>
Sharepoint 2013搜索服务配置总结(实战)
查看>>
博客盈利请先考虑这七点
查看>>
使用 XMLBeans 进行编程
查看>>
写接口请求类型为get或post的时,参数定义的几种方式,如何用注解(原创)--雷锋...
查看>>
【OpenJ_Bailian - 2287】Tian Ji -- The Horse Racing (贪心)
查看>>
Java网络编程--socket服务器端与客户端讲解
查看>>
List_统计输入数值的各种值
查看>>