HDU 4859 海岸线(最小割+最大独立点权变形)

Posted 谦谦君子,陌上其华

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\n",++kase,(n+1)*(m+2)+(n+2)*(m+1)-ans);
157     }
158     return 0;
159 }

 

以上是关于HDU 4859 海岸线(最小割+最大独立点权变形)的主要内容,如果未能解决你的问题,请参考以下文章

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

hdu 4859 海岸线 Bestcoder Round 1

hdu 1569 &1565 (二分图带权最大独立集 - 最小割应用)

HDU 1569 方格取数 << 最大点权独立集

HDU 1565:方格取数(最大点权独立集)***

HDU 1565 1569 方格取数(最大点权独立集)