博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
洛谷P2774 方格取数问题(最小割)
阅读量:6598 次
发布时间:2019-06-24

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

 

考虑一下,答案就是全局和减去舍弃和

不难发现,如果我们按行数+列数的奇偶性分为两类,那么每一类中的数必然互不相邻

那么我们把原图的点分为黑点和白点两类,原地向白点连边,黑点向汇点连边,容量为点权,然后白点向相邻的黑点连边

考虑一下,不能有相邻的,就是在残留网络中不能有$s->u->v->t$这一条路径,那么肯定要在某一个地方割掉。然后要求和最大,所以求得是最小割

然后最小割等于最大流,求一下最大流即可

1 //minamoto 2 #include
3 #include
4 #include
5 #include
6 #define inf 0x3f3f3f3f 7 using namespace std; 8 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 9 char buf[1<<21],*p1=buf,*p2=buf;10 inline int read(){11 #define num ch-'0'12 char ch;bool flag=0;int res;13 while(!isdigit(ch=getc()))14 (ch=='-')&&(flag=true);15 for(res=num;isdigit(ch=getc());res=res*10+num);16 (flag)&&(res=-res);17 #undef num18 return res;19 }20 const int N=10005,M=100005;21 int dx[]={
1,-1,0,0},dy[]={
0,0,1,-1};22 int ver[M],Next[M],edge[M],head[N],dep[N],cur[N],tot=1;23 int n,m,s,t,ans;24 queue
q;25 inline void add(int u,int v,int e){26 ver[++tot]=v,Next[tot]=head[u],head[u]=tot,edge[tot]=e;27 ver[++tot]=u,Next[tot]=head[v],head[v]=tot,edge[tot]=0;28 }29 bool bfs(){30 memset(dep,-1,sizeof(dep));31 while(!q.empty()) q.pop();32 for(int i=0;i<=n*m+1;++i) cur[i]=head[i];33 q.push(s),dep[s]=0;34 while(!q.empty()){35 int u=q.front();q.pop();36 for(int i=head[u];i;i=Next[i]){37 int v=ver[i];38 if(dep[v]<0&&edge[i]){39 dep[v]=dep[u]+1,q.push(v);40 if(v==t) return true;41 }42 }43 }44 return false;45 }46 int dfs(int u,int limit){47 if(!limit||u==t) return limit;48 int flow=0,f;49 for(int i=cur[u];i;i=Next[i]){50 int v=ver[i];cur[u]=i;51 if(dep[v]==dep[u]+1&&(f=dfs(v,min(limit,edge[i])))){52 flow+=f,limit-=f;53 edge[i]-=f,edge[i^1]+=f;54 if(!limit) break;55 }56 }57 return flow;58 }59 int dinic(){60 int flow=0;61 while(bfs()) flow+=dfs(s,inf);62 return flow;63 }64 int main(){65 n=read(),m=read();66 s=0,t=n*m+1;67 for(int i=1;i<=n;++i)68 for(int j=1;j<=m;++j){69 int x=read();ans+=x;70 int id=(i-1)*m+j;71 ((i+j)&1)?(add(s,id,x)):(add(id,t,x));72 }73 for(int i=1;i<=n;++i)74 for(int j=1;j<=m;++j)75 if((i+j)&1){76 int id=(i-1)*m+j;77 for(int k=0;k<4;++k){78 int xx=i+dx[k],yy=j+dy[k];79 if(xx<=0||xx>n||yy<=0||yy>m) continue;80 add(id,(xx-1)*m+yy,inf);81 }82 }83 printf("%d\n",ans-dinic());84 return 0;85 }

 

转载于:https://www.cnblogs.com/bztMinamoto/p/9502199.html

你可能感兴趣的文章
27-列表解析
查看>>
Java并发--线程安全策略
查看>>
python书籍分类和评语(不断更新)
查看>>
iOS 7用户界面过渡指南
查看>>
ansible变量定义
查看>>
smack 监听不同packet机制
查看>>
用例图
查看>>
“#51CTO学院四周年#互相交流,共同提高!
查看>>
同样是做内容创业,你为什么没有别人赚得多?
查看>>
检查Linux系统日志error和mysql错误日志的脚本
查看>>
高效制冷与自然冷却并重
查看>>
SQL Server 2008 全文搜索的一些知识
查看>>
GUN as 使用
查看>>
TCPDUMP快速入门手册
查看>>
【转】Ubuntu13.04配置:Vim+Syntastic+Vundle+YouCompleteMe
查看>>
Nginx学习之二-配置项解析及编程实现
查看>>
[Effective Java]第十一章 序列化
查看>>
[算法导论]红黑树实现(插入和删除) @ Python
查看>>
iPhone开发 数据持久化总结(终结篇)—5种数据持久化方法对比
查看>>
使用ReaderWriterLock类实现多用户读/单用户写同步
查看>>