博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Topcoder SRM558 1000 SurroundingGame
阅读量:6811 次
发布时间:2019-06-26

本文共 2699 字,大约阅读时间需要 8 分钟。

题意:给定一个网格,每个网格有选取代价和占据收益。每个点被占据,需要满足以下两个条件至少一个条件:1.被选取  2.邻近方格都被选取(有公共边被称为邻近)  不一定要占据所有方格,求最大收益。

第一直观感受和文理分科那道题很像,这类肯定用最小割,这种题一般都这样搞,但是建图是个大问题。这道题建出来的图要满足,如果一个点要保留收益,那么要么自己的花费边被割,要么邻近的被割,怎么建呢?

考虑先黑白染色,拆点,然后我们S连向黑色,容量为花费,黑色向自己的分身连收益边,并且黑色向相邻的白色点的分身连INF,黑色分身向白色连INF,白色分身向自己连收益,白色向T连花费。

仔细观察我们发现,确实能满足要求。

这种题一般都是套路,我也不知道怎么就要这么建边,不过可以总结出一些东西,比如一旦有关系,两者之间都会连INF以确保能彼此影响又不会被最小割割中,然后花费和收益,拆点怎么安排就要看具体的题目了。

上代码(与原题的输入不一样,是自己写的)

#include
using namespace std;#define N 25#define INF 1e9#define id(x,y) ((x-1)*m+y)inline int read(){ int x=0,f=1; char a=getchar(); while(a<'0' || a>'9') {
if(a=='-') f=-1; a=getchar();} while(a>='0' && a<='9') x=x*10+a-'0',a=getchar(); return x*f;}const int dir[4][2]={
1,0,-1,0,0,1,0,-1};int n,m,be[N][N],co[N][N],S,T,P,ans,d[1005],head[1005],cur[1005],cnt;bool vis[1005];queue
q;struct edges{ int to,cap,flow,next;}e[2005];inline void insert(int u,int v,int c){ e[cnt]=(edges){v,c,0,head[u]};head[u]=cnt++; e[cnt]=(edges){u,0,0,head[v]};head[v]=cnt++;}inline bool bfs(){ memset(vis,0,sizeof(vis)); vis[S]=1; d[S]=0; q.push(S); while(!q.empty()){ int x=q.front(); q.pop(); for(int i=head[x];i>=0;i=e[i].next){ if(!vis[e[i].to] && e[i].cap>e[i].flow) d[e[i].to]=d[x]+1,q.push(e[i].to),vis[e[i].to]=1; } } return vis[T];}int dfs(int x,int a){ if(x==T || !a) return a; int f,flow=0; for(int& i=cur[x];i>=0;i=e[i].next){ if(d[e[i].to]==d[x]+1 && (f=dfs(e[i].to,min(a,e[i].cap-e[i].flow)))>0) e[i].flow+=f,flow+=f,e[i^1].flow-=f,a-=f; if(!a) break; } return flow;}inline int maxflow(){ int flow=0; while(bfs()){ for(int i=S;i<=T;i++) cur[i]=head[i]; flow+=dfs(S,INF); } return flow;}int main(){ memset(head,-1,sizeof(head)); n=read(); m=read(); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) be[i][j]=read(),ans+=be[i][j]; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) co[i][j]=read(); S=0; T=2*n*m+1; P=n*m; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ int x,y; if((i+j)%2){ insert(S,id(i,j),co[i][j]),insert(id(i,j),id(i,j)+P,be[i][j]); for(int k=0;k<4;k++){ x=i+dir[k][0],y=j+dir[k][1]; if(x<1 || x>n || y<1 || y>m) continue; insert(id(i,j),id(x,y)+P,INF); insert(id(i,j)+P,id(x,y),INF); } } else insert(id(i,j)+P,id(i,j),be[i][j]),insert(id(i,j),T,co[i][j]); } ans-=maxflow(); printf("%d\n",ans); return 0;}

 

转载于:https://www.cnblogs.com/enigma-aw/p/6236241.html

你可能感兴趣的文章
zwPython,字王集成式python开发平台,比pythonXY更强大、更方便。
查看>>
sql常用语句集合(工作总结)
查看>>
C#学习笔记(一)
查看>>
【转】Ubuntu 16.04安装配置TensorFlow GPU版本
查看>>
Cocos2d-x开发---改变父节点颜色、透明度影响子节点
查看>>
借助mapshaper的简化来修复geojson的拓扑错误
查看>>
实验五
查看>>
无废话WCF入门教程五[WCF的通信模式]
查看>>
linux下mysql-5.6忘记root密码,重置root密码详细过程
查看>>
滚动视图,这个好玩
查看>>
微服务下flask和celery的通信
查看>>
iOS开发基础 - UIDataDetectorTypes
查看>>
hdu 1907 John (Nim变形)
查看>>
linkin大话设计模式--命令模式
查看>>
C++中的namespace(using namespace)的理解
查看>>
OCP47:155
查看>>
python局域网alive ip侦听
查看>>
oracle参数文件spfile和pfile
查看>>
convert2Mp4 code snippet
查看>>
netty高级篇(3)-HTTP协议开发
查看>>