zoukankan      html  css  js  c++  java
  • HDU 4859(Bestcoder #1 1003)海岸线(网络流之最小割)

    题目地址:HDU4859

    做了做杭电多校,知识点会的太少了。还是将重点放在刷专题补知识点上吧,明年的多校才是重点。

    这题题目求的最长周长。能够试想一下,这里的海岸线一定是在“.”和“D”之间的,也就是说求最多的相邻的“.”和“D”的配对对数。能够先转化成最小割求最小配对对数,由于总对数是一定的。仅仅须要减去即可。

    要先对周围填充上一圈的“D”。然后变成了一个(n+2)*(m+2)的矩形。由于要求的都是相邻的匹配数,所以能够利用黑白染色转化成一个二分图模型,对于每对相邻的进行加边。

    二分图已经分成了X集和Y集两个子集合。如果要把全部的“.”都要分到X集,全部的"D"都要分到Y集(不过如果),这时候分两种情况讨论:

    1:若当前点在地图上是 . 可是却被分到了Y集,或者当前点是 D ,却被分到了X集。就和源点连一条INF的边。

    2:若当前点在地图上是 . 而且被分到了X集,或者当前点是 D ,被分到了Y集,就和汇点连一条INF的边。

    分析一下就知道,仅仅有 . --> . 或者 D --> D ,也就是类型同样的。才干从源流向汇。

    源连接的点是“分错了”的点( X集的D或者Y集的. ),汇连接的点是“分对了”的点(X集的.或者Y集的D),所以假设要从源流到汇,则一定是D->D或者.->.。也就是同样类型的,求出最小割就是最小化同样的。

    最后用总对数减去这个就是答案.

    代码例如以下:

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <ctype.h>
    #include <queue>
    #include <map>
    #include<algorithm>
    using namespace std;
    const int INF=0x3f3f3f3f;
    int head[3000], source, sink, nv, cnt;
    int cur[3000], num[3000], d[3000], pre[3000];
    int jx[]={0,0,1,-1};
    int jy[]={1,-1,0,0};
    struct node
    {
        int u, v, cap, next;
    }edge[1000000];
    void add(int u, int v, int cap)
    {
        edge[cnt].v=v;
        edge[cnt].cap=cap;
        edge[cnt].next=head[u];
        head[u]=cnt++;
    
        edge[cnt].v=u;
        edge[cnt].cap=0;
        edge[cnt].next=head[v];
        head[v]=cnt++;
    }
    void bfs()
    {
        memset(d,-1,sizeof(d));
        memset(num,0,sizeof(num));
        queue<int>q;
        q.push(sink);
        d[sink]=0;
        num[0]=1;
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            for(int i=head[u];i!=-1;i=edge[i].next)
            {
                int v=edge[i].v;
                if(d[v]==-1)
                {
                    d[v]=d[u]+1;
                    num[d[v]]++;
                    q.push(v);
                }
            }
        }
    }
    int isap()
    {
        memcpy(cur,head,sizeof(cur));
        bfs();
        int flow=0, u=pre[source]=source, i;
        while(d[source]<nv)
        {
            if(u==sink)
            {
                int f=INF, pos;
                for(i=source;i!=sink;i=edge[cur[i]].v)
                {
                    if(f>edge[cur[i]].cap)
                    {
                        f=edge[cur[i]].cap;
                        pos=i;
                    }
                }
                for(i=source;i!=sink;i=edge[cur[i]].v)
                {
                    edge[cur[i]].cap-=f;
                    edge[cur[i]^1].cap+=f;
                }
                flow+=f;
                u=pos;
            }
            for(i=cur[u];i!=-1;i=edge[i].next)
            {
                if(d[edge[i].v]+1==d[u]&&edge[i].cap) break;
            }
            if(i!=-1)
            {
                cur[u]=i;
                pre[edge[i].v]=u;
                u=edge[i].v;
            }
            else
            {
                if(--num[d[u]]==0) break;
                int mind=nv;
                for(i=head[u];i!=-1;i=edge[i].next)
                {
                    if(mind>d[edge[i].v]&&edge[i].cap)
                    {
                        mind=d[edge[i].v];
                        cur[u]=i;
                    }
                }
                d[u]=mind+1;
                num[d[u]]++;
                u=pre[u];
            }
        }
        return flow;
    }
    int main()
    {
        int t, n, m, i, j, mp[60][60], num=0;
        char s[60];
        scanf("%d",&t);
        while(t--)
        {
            num++;
            scanf("%d%d",&n,&m);
            memset(mp,0,sizeof(mp));
            for(i=1;i<=n;i++)
            {
                scanf("%s",s);
                for(j=0;j<m;j++)
                {
                    if(s[j]=='E')
                        mp[i][j+1]=2;
                    else if(s[j]=='.')
                        mp[i][j+1]=1;
                }
            }
            cnt=0;
            memset(head,-1,sizeof(head));
            source=0;
            sink=(n+2)*(m+2)+1;
            nv=sink+1;
            for(i=0;i<=n+1;i++)
            {
                for(j=0;j<=m+1;j++)
                {
                    if((i+j)%2==0)
                    {
                        if(mp[i][j]==1)
                        {
                            add(i*(m+2)+j+1,sink,INF);
                        }
                        else if(mp[i][j]==0)
                        {
                            add(source,i*(m+2)+j+1,INF);
                        }
                    }
                    else
                    {
                        if(mp[i][j]==0)
                        {
                            add(i*(m+2)+j+1,sink,INF);
                        }
                        else if(mp[i][j]==1)
                        {
                            add(source,i*(m+2)+j+1,INF);
                        }
                    }
                    for(int k=0;k<4;k++)
                    {
                        int x=i+jx[k];
                        int y=j+jy[k];
                        if(x>=0&&x<=n+1&&y>=0&&y<=m+1)
                        {
                            add(i*(m+2)+j+1,x*(m+2)+y+1,1);
                        }
                    }
                }
            }
            int ans;
            ans=isap();
            printf("Case %d: %d
    ",num,(n+1)*(m+2)+(n+2)*(m+1)-ans);
        }
        return 0;
    }
    



  • 相关阅读:
    利用自定义分页技术提高数据库性能
    solr深分页,游标操作分页,解决性能问题
    Selenium2+python自动化54-unittest生成测试报告(HTMLTestRunner)
    Selenium2+python自动化53-unittest批量执行(discover)
    Selenium2+python自动化52-unittest执行顺序
    Selenium2+python自动化51-unittest简介
    Fiddler抓包2-只抓APP的请求
    selenium3+python自动化50-环境搭建(firefox)
    Selenium2+python自动化49-判断文本(text_to_be_present_in_element)
    Selenium2+python自动化47-判断弹出框存在(alert_is_present)
  • 原文地址:https://www.cnblogs.com/yxwkf/p/5184270.html
Copyright © 2011-2022 走看看