首先,我们要读懂这道题,否则你会和我一开始产生一样的疑问,把所有的数都取走剩下一个最小的不就可以了么???然后我们发现样例完全不是这么回事。题目中所说的使相邻的两个数没有公共边,是指你去走的数,也就是取完之后矩阵里的空白格子。明白了这一点,我们可能会有一个比较基础的贪心思想,没错,就是隔一个取一个,但是这么做并不可行,具体反例很容易找。然后我们通过观察,发现这道题和某最大权闭合子图有些类似,如果我们全取所有点,删去最小割说不准可行。
开始考虑建图,首先所有的奇数格子连源点,偶数格子连汇点,边权为点权。他们之间的边只连奇数到偶数的,边权为inf,这么连是为了避免重复计算。然后直接DINIC最大流就可以了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define ll long long
#define inf 50000000
#define re register
#define id m*(i-1)+j
using namespace std;
struct po
{
int from,to,dis,nxt;
}edge[];
int head[],cur[],dep[],n,m,s,t,u,num=-,x,y,l,tot,sum,d;
int nm,a[][];
int dx[]={,,,-,};
int dy[]={,,,,-};
inline int read()
{
int x=,c=;
char ch=' ';
while((ch>''||ch<'')&&ch!='-')ch=getchar();
while(ch=='-')c*=-,ch=getchar();
while(ch<=''&&ch>='')x=x*+ch-'',ch=getchar();
return x*c;
}
inline void add_edge(int from,int to,int dis)
{
edge[++num].nxt=head[from];
edge[num].from=from;
edge[num].to=to;
edge[num].dis=dis;
head[from]=num;
}
inline void add(int from,int to,int dis)
{
add_edge(from,to,dis);
add_edge(to,from,);
}
inline bool bfs()
{
memset(dep,,sizeof(dep));
queue<int> q;
while(!q.empty())
q.pop();
dep[s]=;
q.push(s);
while(!q.empty())
{
int now=q.front();
q.pop();
for(re int i=head[now];i!=-;i=edge[i].nxt)
{
int v=edge[i].to;
if(dep[v]==&&edge[i].dis>)
{
dep[v]=dep[now]+;
if(v==t)
return ;
q.push(v);
}
}
}
return ;
}
inline int dfs(int u,int dis)
{
if(u==t)
return dis;
int diss=;
for(re int i=head[u];i!=-;i=edge[i].nxt)
{
int v=edge[i].to;
if(dep[v]==dep[u]+&&edge[i].dis!=)
{
int check=dfs(v,min(dis,edge[i].dis));
if(check>)
{
diss+=check;
dis-=check;
edge[i].dis-=check;
edge[i^].dis+=check;
if(dis==) break;
}
}
}
return diss;
}
inline int dinic()
{
int ans=;
while(bfs())
{
for(re int i=;i<=t;i++)
cur[i]=head[i];
while(int d=dfs(s,inf))
ans+=d;
}
return ans;
}
int main()
{
memset(head,-,sizeof(head));
n=read();m=read();
s=;t=n*m+;
for(re int i=;i<=n;i++)
for(re int j=;j<=m;j++)
a[i][j]=read(),sum+=a[i][j];
for(re int i=;i<=n;i++)
for(re int j=;j<=m;j++)
{
if((i+j)%==)
add(s,id,a[i][j]);
else
add(id,t,a[i][j]);
for(re int h=;h<=;h++)
{
int lx=i+dx[h],ly=j+dy[h];
if(lx>=&&lx<=n&&ly>=&&ly<=m)
if((lx+ly)%!=)
add(id,(lx-)*m+ly,inf);
}
}
cout<<sum-dinic();
}

【P2774】方格取数问题(贪心+最大流,洛谷)的更多相关文章

  1. P2774 方格取数问题 网络最大流 割

    P2774 方格取数问题:https://www.luogu.org/problemnew/show/P2774 题意: 给定一个矩阵,取出不相邻的数字,使得数字的和最大. 思路: 可以把方格分成两个 ...

  2. P2774 方格取数问题 网络流

    题目: P2774 方格取数问题 题目背景 none! 题目描述 在一个有 m*n 个方格的棋盘中,每个方格中有一个正整数.现要从方格中取数,使任意 2 个数所在方格没有公共边,且取出的数的总和最大. ...

  3. P2774 方格取数问题(最小割)

    P2774 方格取数问题 一看题目便知是网络流,但由于无法建图.... 题目直说禁止那些条件,这导致我们直接建图做不到,既然如此,我们这是就要逆向思维,他禁止那些边,我们就连那些边. 我们将棋盘染色, ...

  4. P2774 方格取数问题(网络流)

    P2774 方格取数问题 emm........仔细一看,这不是最大权闭合子图的题吗! 取一个点$(x,y)$,限制条件是同时取$(x,y+1),(x,y-1),(x+1,y),(x-1,y)$,只不 ...

  5. 洛谷 P2774 方格取数问题 解题报告

    P2774 方格取数问题 题目背景 none! 题目描述 在一个有 \(m*n\) 个方格的棋盘中,每个方格中有一个正整数.现要从方格中取数,使任意 2 个数所在方格没有公共边,且取出的数的总和最大. ...

  6. P2774 方格取数问题 网络流重温

    P2774 方格取数问题 这个题目之前写过一次,现在重温还是感觉有点难,可能之前没有理解透彻. 这个题目要求取一定数量的数,并且这些数在方格里面不能相邻,问取完数之后和最大是多少. 这个很好的用了网络 ...

  7. P2774 方格取数(网络流)

    https://www.luogu.com.cn/problem/P2774 在一个有 m×n 个方格的棋盘中,每个方格中有一个正整数. 现要从方格中取数,使任意2个数所在方格没有公共边,且取出的数的 ...

  8. 【wikioi】1907 方格取数3(最大流+最大权闭合子图)

    http://www.wikioi.com/problem/1907/ 这题我一开始想到的是状压,看到n<=30果断放弃. 然后也想到了黑白染色,然后脑残了,没想到怎么连边. 很简单的一题 黑白 ...

  9. 洛谷 P2045 方格取数加强版【费用流】

        题目链接:https://www.luogu.org/problemnew/show/P2045 题目描述 给出一个n*n的矩阵,每一格有一个非负整数Aij,(Aij <= 1000)现 ...

  10. 【Codevs1227】方格取数2(费用流)

    题意:给出一个n*n的矩阵,每一格有一个非负整数Aij,(Aij <= 1000) 现在从(1,1)出发,可以往右或者往下走,最后到达(n,n),每达到一格,把该格子的数取出来,该格子的数就变成 ...

随机推荐

  1. 集合 Vector ArrayList 集合一

    集合是存储对象的,与对象数组不同,集合可以自动的扩大自己的容量,像StringBuffer一样,存储的对象类型可以不一致,(object数组). 方法: add();remove();get();se ...

  2. 48、ViewFlow ---- 滑动广告页

    <!-- main.xml --> <?xml version="1.0" encoding="utf-8"?> <LinearL ...

  3. CodeMirror:基于JavaScript的代码编辑器

    官方网站定义: http://codemirror.net/ CodeMirror is a versatile text editor implemented in JavaScript for t ...

  4. codevs2894、2837、1669、2503、3231

    6.25动态规划之背包回顾 2894 Txx考试  时间限制: 1 s  空间限制: 32000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description Txx是一个 ...

  5. using 关键字的使用

    using 关键字的使用主要分为两种类型:using declaration(using 声明)和using directive(using 命令): using 声明:引入特定名称空间中的一个成员. ...

  6. 利用Google Analytics API实现自己的统计报表

    Google Analytics 简称 GA,功能实在是太强大了,正因如此,导致调研GA API花费了大量的时间,太多的名词需要梳理. 正确的学习步骤是: 首先,找个有权限的账号,登录GA(https ...

  7. dfs_部分和问题

    给定整数a1,a2,....,an ,选若干数时它们的和为k. 解析:每个数有两种状态:加.不加. 全部n个数都决定其状态后进行判断.复杂度O(2n) 生成可行解空间多用dfs实现. import j ...

  8. <..................> 哈佛大学哲学系 && 历史哲学笔记文献集

    哈佛大学哲学系课程表            (一)概况    (1)哈佛大学哲学系现有教师21人,其中访问教授7人,教师流动性较大,每年有一定的变化.以下为现任教师:Richard Moran(系主任 ...

  9. python基本数据类型之操作

    python注释 当行注视:# 被注释内容多行注释:""" 被注释内容 """ 字符串操作 # 代表单行注释                ...

  10. python构造wireshark可以解析的LTE空口数据

    Wireshark是可以解析LTE的空口数据.但是在wireshark的实现中,这些数据都是被封装到UDP报文中.然后根据wireshark的格式文件对LTE的数据加上头信息.头信息的定义参考附件pa ...