zoukankan      html  css  js  c++  java
  • 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
    ",cas,temp/2-now);
        }
    }
  • 相关阅读:
    微信支付:redirect-uri参数错误 的解决办法
    PHP计划任务之关闭浏览器后仍然继续执行的函数
    windows7安装phpnow Apache非管理员权限不能操作Windows NT服务的解决方法
    php 本周开始时间和结束时间;本月开始时间结束时间;上月开始时间结束时间
    图片预览
    生成随机验证码(记得下载字体文件啊)
    git ,github实际操作指南
    git,github初识命令
    博客园项目(BBS)
    django之分页器
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5126034.html
Copyright © 2011-2022 走看看