• 【HDU4859】 海岸线(网络流-最小割)


    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<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<queue>
      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<y?x:y;}
     29 
     30 void ins(int x,int y,int f)
     31 {
     32     if(f==0) return; 
     33     t[++len].x=x;t[len].y=y;t[len].f=f;
     34     t[len].next=first[x];first[x]=len;t[len].o=len+1;
     35     t[++len].x=y;t[len].y=x;t[len].f=0;
     36     t[len].next=first[y];first[y]=len;t[len].o=len-1;
     37 }
     38 
     39 queue<int > 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<m;j++)
     96             {
     97                 if(s[j]=='E') map[i][j+1]=0;
     98                 else if(s[j]=='.') map[i][j+1]=1;
     99                 else map[i][j+1]=2;
    100             }
    101         }
    102         
    103         int ans=2*n*m+n+m;
    104         for(int i=0;i<=m+1;i++) map[0][i]=2,map[n+1][i]=2;
    105         for(int i=0;i<=n+1;i++) map[i][0]=2,map[i][m+1]=2;
    106         
    107         memset(s1,0,sizeof(s1));
    108         memset(s2,0,sizeof(s2));
    109         for(int i=1;i<=n;i++)
    110          for(int j=1;j<=m;j++) if(map[i][j]!=0)
    111          {
    112              int now=i*(m+2)+j;
    113              for(int k=1;k<=4;k++)
    114              {
    115                  int nx=i+dx[k],ny=j+dy[k];
    116                  if(map[i][j]==1) s1[nx][ny]++;
    117                  if(map[i][j]==2) s2[nx][ny]++;
    118                  if((nx==0||ny==0||nx==n+1||ny==m+1)&&map[i][j]==2) ans--;
    119                  else if(map[nx][ny]!=0&&map[nx][ny]==map[i][j]&&k<=2)    ans--;
    120              }
    121          }
    122         for(int i=1;i<=m;i++) s2[1][i]++,s2[n][i]++;
    123         for(int i=1;i<=n;i++) s2[i][1]++,s2[i][m]++;
    124         memset(first,0,sizeof(first));
    125         len=0;int cnt=2;
    126         st=1,ed=2;
    127         for(int i=1;i<=n;i++)
    128          for(int j=1;j<=m;j++) if(map[i][j]==0)
    129          {
    130              int now=++cnt;num[i][j]=cnt;
    131              if((i+j)%2==0) {ins(now,ed,s2[i][j]);ins(st,now,s1[i][j]);}
    132              else {ins(now,ed,s1[i][j]);ins(st,now,s2[i][j]);}
    133              for(int k=1;k<=2;k++)
    134              {
    135                  int nx=i+dx[k],ny=j+dy[k];
    136                  if(nx<1||nx>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
    ",++kase,ans);
    144     }
    145     return 0;
    146 }
    [HDU4859]

    2016-05-17 16:42:42

  • 相关阅读:
    UIWebView 视频播放获取开始播放和结束播放通知
    显示图像数据的高级接口 UIImage
    如何跳到系统设置里的WiFi界面
    Objective-C 去掉NSString 前后中空格
    iOS 属性修饰符的区别
    iOS 线程锁同步机制
    XCode 6 以后使用编程处理一些图片效果
    iOS 精益编程
    iOS7以后UITextView 技巧
    2016年12月英语六级阅读真题及答案 第3套
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/5502241.html
Copyright © 2020-2023  润新知