zoukankan      html  css  js  c++  java
  • HDU 4859 海岸线(最小割+最大独立点权变形)

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

    题意:

    欢迎来到珠海!
    由于土地资源越来越紧张,使得许多海滨城市都只能依靠填海来扩展市区以求发展。作为Z市的决策人,在仔细观察了Z市地图之后,你准备通过填充某些海域来扩展Z市的海岸线到最长,来吸引更多的游客前来旅游度假。为了简化问题,假设地图为一个N*M的格子,其中一些是陆地,一些是可以填充的浅海域,一些是不可填充的深海域。这里定义海岸线的长度为一个联通块陆地(可能包含浅海域填充变为的陆地)的边缘长度,两个格子至少有一个公共边,则视为联通。
    值得注意的是,这里Z市的陆地区域可以是不联通的,并且整个地图都处在海洋之中,也就是说,Z市是由一些孤岛组成的,比如像,夏威夷?
    你的任务是,填充某些浅海域,使得所有岛屿的海岸线之和最长。

    思路:
    这道题目的话和最大独立点权是比较相似的。

    首先考虑一个格子的情况,它的海岸线长度之和就是它周围有多少海域,如果它四条边都是海域,那么它的海岸线长度之和就是4,如果周围有陆地则会相应的减少。

    那么其实这道题目就是要我们求最大相邻的'D'和'.' 的总对数!!

    先在格子周围加上一圈'D',先将这个图分成一个二分图,左边为X集,右边为Y集(X与源点相连,表示陆地,Y与汇点相连,表示海域),接下来分析每个格子:

    1、若相邻则连边,容量1。

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

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

    所以只有 . --> . 或者 D --> D ,也就是类型相同的,才能从源流向汇。此时需要减少1的海岸线,因为不是'.'与'D'相邻。最小割求出最小的相同格子相邻的对数。

      1 #include<iostream>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<vector>
      6 #include<stack>
      7 #include<queue>
      8 #include<cmath>
      9 #include<map>
     10 #include<set>
     11 using namespace std;
     12 typedef long long ll;
     13 typedef pair<int,int> pll;
     14 const int INF = 0x3f3f3f3f;
     15 const int maxn=1e6+5;
     16 
     17 int n, m;
     18 int mp[60][60];
     19 
     20 int dx[]={0,0,1,-1};
     21 int dy[]={1,-1,0,0};
     22 
     23 struct Edge
     24 {
     25     int from,to,cap,flow;
     26     Edge(int u,int v,int w,int f):from(u),to(v),cap(w),flow(f){}
     27 };
     28 
     29 struct Dinic
     30 {
     31     int n,m,s,t;
     32     vector<Edge> edges;
     33     vector<int> G[maxn];
     34     bool vis[maxn];
     35     int cur[maxn];
     36     int d[maxn];
     37 
     38     void init(int n)
     39     {
     40         this->n=n;
     41         for(int i=0;i<n;++i) G[i].clear();
     42         edges.clear();
     43     }
     44 
     45     void AddEdge(int from,int to,int cap)
     46     {
     47         edges.push_back( Edge(from,to,cap,0) );
     48         edges.push_back( Edge(to,from,0,0) );
     49         m=edges.size();
     50         G[from].push_back(m-2);
     51         G[to].push_back(m-1);
     52     }
     53 
     54     bool BFS()
     55     {
     56         queue<int> Q;
     57         memset(vis,0,sizeof(vis));
     58         vis[s]=true;
     59         d[s]=0;
     60         Q.push(s);
     61         while(!Q.empty())
     62         {
     63             int x=Q.front(); Q.pop();
     64             for(int i=0;i<G[x].size();++i)
     65             {
     66                 Edge& e=edges[G[x][i]];
     67                 if(!vis[e.to] && e.cap>e.flow)
     68                 {
     69                     vis[e.to]=true;
     70                     d[e.to]=d[x]+1;
     71                     Q.push(e.to);
     72                 }
     73             }
     74         }
     75         return vis[t];
     76     }
     77 
     78     int DFS(int x,int a)
     79     {
     80         if(x==t || a==0) return a;
     81         int flow=0, f;
     82         for(int &i=cur[x];i<G[x].size();++i)
     83         {
     84             Edge &e=edges[G[x][i]];
     85             if(d[e.to]==d[x]+1 && (f=DFS(e.to,min(a,e.cap-e.flow) ) )>0)
     86             {
     87                 e.flow +=f;
     88                 edges[G[x][i]^1].flow -=f;
     89                 flow +=f;
     90                 a -=f;
     91                 if(a==0) break;
     92             }
     93         }
     94         return flow;
     95     }
     96 
     97     int Maxflow(int s,int t)
     98     {
     99         this->s=s; this->t=t;
    100         int flow=0;
    101         while(BFS())
    102         {
    103             memset(cur,0,sizeof(cur));
    104             flow +=DFS(s,INF);
    105         }
    106         return flow;
    107     }
    108 }DC;
    109 
    110 int main()
    111 {
    112     //freopen("in.txt", "r", stdin);
    113     char s[60];
    114     int kase=0;
    115     int T;
    116     scanf("%d",&T);
    117     while(T--)
    118     {
    119         memset(mp,0,sizeof(mp));
    120         scanf("%d%d",&n,&m);
    121         for(int i=1;i<=n;i++)
    122         {
    123             scanf("%s",s);
    124             for(int j=0;j<m;j++)
    125             {
    126                 if(s[j]=='E')  mp[i][j+1]=2;
    127                 else if(s[j]=='.')  mp[i][j+1]=1;
    128             }
    129         }
    130         int src=0,dst=(n+2)*(m+2)+1;
    131         DC.init(dst+1);
    132         for(int i=0;i<=n+1;i++)
    133         {
    134             for(int j=0;j<=m+1;j++)
    135             {
    136                 if((i+j)%2==0)
    137                 {
    138                     if(mp[i][j]==1)  DC.AddEdge(i*(m+2)+j+1,dst,INF);
    139                     else if(mp[i][j]==0)  DC.AddEdge(src,i*(m+2)+j+1,INF);
    140                 }
    141                 else
    142                 {
    143                     if(mp[i][j]==0)  DC.AddEdge(i*(m+2)+j+1,dst,INF);
    144                     else if(mp[i][j]==1)  DC.AddEdge(src,i*(m+2)+j+1,INF);
    145                 }
    146                 for(int k=0;k<4;k++)
    147                 {
    148                     int x=i+dx[k];
    149                     int y=j+dy[k];
    150                     if(x<0 || x>n+1 || y<0 || y>m+1)  continue;
    151                     DC.AddEdge(i*(m+2)+j+1,x*(m+2)+y+1,1);
    152                 }
    153             }
    154         }
    155         int ans=DC.Maxflow(src,dst);
    156         printf("Case %d: %d
    ",++kase,(n+1)*(m+2)+(n+2)*(m+1)-ans);
    157     }
    158     return 0;
    159 }
  • 相关阅读:
    bind函数
    尾置返回类型
    lambda表达式
    C++谓词
    capacity和size
    容器操作可能会使迭代器失效
    特殊的forward_list操作
    向顺序容器添加元素
    swap与assign
    迭代器
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/7594385.html
Copyright © 2011-2022 走看看