hdu 4859 海岸线 最小割

海岸线

题目连接:

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

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

题意

题解:

题目很显然就是要求D和.相邻的边,个数最多,我们转换一下,就是求相邻的边相同的最少。

求最小割模型

黑白染色之后,E无视,如果黑色的.或者白色的D,我们就连S,否则连T,容量都是INF

这样建边后,如果要从源点流向汇点,那么肯定是.->.或者D->D

所以求最小割就好了

代码

#include<bits/stdc++.h>
using namespace std;
const int MAXN=100000,MAXM=100000,inf=1e9;
struct Edge
{
    int v,c,f,nx;
    Edge() {}
    Edge(int v,int c,int f,int nx):v(v),c(c),f(f),nx(nx) {}
} E[MAXM];
int G[MAXN],cur[MAXN],pre[MAXN],dis[MAXN],gap[MAXN],N,sz;
void init(int _n)
{
    N=_n,sz=0; memset(G,-1,sizeof(G[0])*N);
}
void link(int u,int v,int c)
{
    E[sz]=Edge(v,c,0,G[u]); G[u]=sz++;
    E[sz]=Edge(u,0,0,G[v]); G[v]=sz++;
}
bool bfs(int S,int T)
{
    static int Q[MAXN]; memset(dis,-1,sizeof(dis[0])*N);
    dis[S]=0; Q[0]=S;
    for (int h=0,t=1,u,v,it;h<t;++h)
    {
        for (u=Q[h],it=G[u];~it;it=E[it].nx)
        {
            if (dis[v=E[it].v]==-1&&E[it].c>E[it].f)
            {
                dis[v]=dis[u]+1; Q[t++]=v;
            }
        }
    }
    return dis[T]!=-1;
}
int dfs(int u,int T,int low)
{
    if (u==T) return low;
    int ret=0,tmp,v;
    for (int &it=cur[u];~it&&ret<low;it=E[it].nx)
    {
        if (dis[v=E[it].v]==dis[u]+1&&E[it].c>E[it].f)
        {
            if (tmp=dfs(v,T,min(low-ret,E[it].c-E[it].f)))
            {
                ret+=tmp; E[it].f+=tmp; E[it^1].f-=tmp;
            }
        }
    }
    if (!ret) dis[u]=-1; return ret;
}
int dinic(int S,int T)
{
    int maxflow=0,tmp;
    while (bfs(S,T))
    {
        memcpy(cur,G,sizeof(G[0])*N);
        while (tmp=dfs(S,T,inf)) maxflow+=tmp;
    }
    return maxflow;
}

char ss[120][120];
int dx[4]={1,-1,0,0};
int dy[4]={0,0,1,-1};
int get(int x,int y)
{
    return (x+1)*105+(y+1)+3;
}
int main()
{
    int t;
    scanf("%d",&t);
    for(int cas=1;cas<=t;cas++)
    {
        int n,m;
        init(50000);
        memset(ss,0,sizeof(ss));
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%s",ss[i]+1);
        for(int i=0;i<=n+1;i++)
            ss[i][0]=ss[i][m+1]='D';
        for(int i=0;i<=m+1;i++)
            ss[0][i]=ss[n+1][i]='D';
        int s = 0,t = 1;
        int temp = 0;
        for(int i=0;i<=n+1;i++)
        {
            for(int j=0;j<=m+1;j++)
            {
                for(int t=0;t<4;t++)
                {
                    int x = i+dx[t];
                    int y = j+dy[t];
                    if(x<0||x>n+1||y<0||y>m+1)continue;
                    link(get(i,j),get(x,y),1);
                    temp++;
                }
                if(ss[i][j]!='E')
                {
                    if( ((i+j)%2 == 1 && ss[i][j] == '.') || ((i+j)%2 == 0 && ss[i][j] == 'D') )
                        link(s,get(i,j),inf);
                    else link(get(i,j),t,inf);
                }
            }
        }
        int now = dinic(s,t);
        printf("Case %d: %d\n",cas,temp/2-now);
    }
}
    原文作者:qscqesze
    原文地址: https://www.cnblogs.com/qscqesze/p/5126034.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞