https://www.luogu.org/problemnew/show/P2774

把两个相邻的节点连边,这些边就是要方便最小割割断其他边存在的,容量无穷。

这种类似的问题的话,把二分图的一部分(黑点)连S,容量为其价值,另一部分(白点)连T,容量也是其价值。

因为上面的边存在我们在最小割的时候需要割断一些边表示这个点不被取到。

但是这个和最大权闭合子图有什么不同呢,为什么白色点好像和最大权闭合子图中的负权点得到了类似的待遇?

是不是可以这样转化,先假设获得了所有黑点白点的权值,因为某些黑点的存在你必须去购买它相邻的白点,付出白点权值的代价,所以白点就是负权点

所以我们要么获得黑色点和他相邻的至多4个白点并付出白点的权值的代价(最小割割断4个白点),要么我们舍弃这个黑色点但不需要购买白点。

!!!

意思就是其实二分图最大独立点集是最大权闭合子图的简化版。

据说还有二分图最小顶点覆盖=二分图顶点数-二分图最大独立点集,不知什么意思。

法克,n和m写反了。

#include<bits/stdc++.h>
using namespace std;
#define ll long long /* dinic begin */ const int MAXN=;
const int MAXM=;
const int INF=0x3f3f3f3f;
struct Edge{
int to,next,cap,flow;
}edge[MAXM]; int tol;
int head[MAXN]; void init(){
tol=;
memset(head,-,sizeof(head));
} void addedge(int u,int v,int w){
edge[tol].to=v;edge[tol].cap=w;edge[tol].flow=;
edge[tol].next=head[u];head[u]=tol++;
edge[tol].to=u;edge[tol].cap=;edge[tol].flow=;
edge[tol].next=head[v];head[v]=tol++;
} int Q[MAXN];
int dep[MAXN],cur[MAXN],sta[MAXN];
bool bfs(int s,int t,int n){
int front=,tail=;
memset(dep,-,sizeof(dep[])*(n+));
dep[s]=;
Q[tail++]=s;
while(front<tail){
int u=Q[front++];
for(int i=head[u];i!=-;i=edge[i].next){
int v=edge[i].to;
if(edge[i].cap>edge[i].flow&&dep[v]==-){
dep[v]=dep[u]+;
if(v==t)
return true;
Q[tail++]=v;
}
}
}
return false;
} int dinic(int s,int t,int n){
//n最后一个节点的编号的下一个编号
int maxflow=;
while(bfs(s,t,n)){
for(int i=;i<n;i++)cur[i]=head[i];
int u=s,tail=;
while(cur[s]!=-){
if(u==t){
int tp=INF;
for(int i=tail-;i>=;i--){
tp=min(tp,edge[sta[i]].cap-edge[sta[i]].flow); }
maxflow+=tp;
for(int i=tail-;i>=;i--){
edge[sta[i]].flow+=tp;
edge[sta[i]^].flow-=tp;
if(edge[sta[i]].cap-edge[sta[i]].flow==)
tail=i;
}
u=edge[sta[tail]^].to; }
else if(cur[u]!=-&&edge[cur[u]].cap>edge[cur[u]].flow
&&dep[u]+==dep[edge[cur[u]].to]){
sta[tail++]=cur[u];
u=edge[cur[u]].to;
}
else{
while(u!=s&&cur[u]==-){
u=edge[sta[--tail]^].to;
}
cur[u]=edge[cur[u]].next;
}
}
}
return maxflow;
} /* dinic end */ int c[][]; int n,m;
int id(int i,int j){
return (i-)*m+j;
} int main(){
init();
scanf("%d%d",&n,&m);
ll sum=;
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
scanf("%d",&c[i][j]);
sum+=c[i][j];
}
} int s=,t=*n*m+;
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
if((i+j)%==){
//黑点
addedge(s,id(i,j),c[i][j]);
}
else{
addedge(id(i,j),t,c[i][j]);
}
}
} for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
if((i+j)%==){
//黑点
if(i>){
addedge(id(i,j),id(i-,j),INF);
}
if(j>){
addedge(id(i,j),id(i,j-),INF);
}
if(i+<=n){
addedge(id(i,j),id(i+,j),INF);
}
if(j+<=m){
addedge(id(i,j),id(i,j+),INF);
}
}
}
} int maxflow=dinic(s,t,t+);
printf("%lld\n",sum-maxflow); }

洛谷 - P2774 - 方格取数问题 - 二分图最大独立点集 - 最小割的更多相关文章

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

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

  2. [洛谷P2774]方格取数问题

    题目大意:给你一个$n\times m$的方格,要求你从中选择一些数,其中没有相邻两个数,使得最后和最大 题解:网络流,最小割,发现相邻的两个点不可以同时选择,进行黑白染色,原点向黑点连一条容量为点权 ...

  3. 洛谷 [P2774] 方格取数问题

    二分图最大点权独立集 通过题目描述我们可以很明显的看出要通过二分图建模,二分图求最大独立点集很容易,就是建立二分图求n-最小割,然而这里加入了权值,而且权值是在点上的,那么我们对于每个点连一条到源点或 ...

  4. 洛谷P2774 方格取数问题(最小割)

    传送门 考虑一下,答案就是全局和减去舍弃和 不难发现,如果我们按行数+列数的奇偶性分为两类,那么每一类中的数必然互不相邻 那么我们把原图的点分为黑点和白点两类,原地向白点连边,黑点向汇点连边,容量为点 ...

  5. 洛谷P2774 方格取数问题(最小割)

    题意 $n \times m$的矩阵,不能取相邻的元素,问最大能取多少 Sol 首先补集转化一下:最大权值 = sum - 使图不连通的最小权值 进行黑白染色 从S向黑点连权值为点权的边 从白点向T连 ...

  6. 洛谷 P2774 方格取数问题【最小割】

    因为都是正整数,所以当然取得越多越好.先把所有点权加起来,黑白染色后,s向所有黑点连流量为点权的边,所有白点向t连流量为点权的边,然后黑点向相邻的四个白点连流量为inf的边,表示不可割,这样一来,对于 ...

  7. 棋盘DP三连——洛谷 P1004 方格取数 &&洛谷 P1006 传纸条 &&Codevs 2853 方格游戏

    P1004 方格取数 题目描述 设有N $\times N$N×N的方格图(N $\le 9$)(N≤9),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字00.如下图所示(见样例): A ...

  8. 洛谷 P1004 方格取数 题解

    P1004 方格取数 题目描述 设有 \(N \times N\) 的方格图 \((N \le 9)\),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字\(0\).如下图所示(见样例): ...

  9. 洛谷 P1004 方格取数 【多进程dp】

    题目链接:https://www.luogu.org/problemnew/show/P1004 题目描述 设有N*N的方格图(N<=9),我们将其中的某些方格中填入正整数,而其他的方格中则放 ...

随机推荐

  1. BUPT复试专题—C翻转(2010)

    https://www.nowcoder.com/practice/74bdb725421c4f80b4aca7266818baf0?tpId=67&tqId=29639&rp=0&a ...

  2. Our happy ending

    题目链接 题意: 输入n.k.L,n个数,最大值不超过L,在序列中取若干个数和能达到k的序列个数 n,k<=20 , 0<=L<=10^9 分析: 题目关键在于和k比較小,所以能够考 ...

  3. Linux安装Axis C构建WebService服务

    在安装Axis C++之前有两个组件是必须安装的,分别是Apache HTTP Server以及用于处理XML的程序Xerces:为了编译Axis以及Apache HTTPD,你的Linux机器还应该 ...

  4. python day 13 生成器 以及 推导式

    1.生成器的本质是迭代器 2.生成器函数 def  fn() 函数体 yield fn() g = fn() 此时这个g就是生成器 所以g 是可迭代的 g._ _next_ _ 每执行一次_ _nex ...

  5. yum 安装 mysql

    安装 yum -y install mysql-server 开机自启动 chkconfig mysqld on 设置账户密码 启动 service mysqld start -- 进入mysql库 ...

  6. JDK提供的几种常用的锁

    可重入互斥锁: Lock lock = new ReentrantLock() lock.lock(); ... lock.unlock(); 信号量: Semaphore semaphore = n ...

  7. Java程序员从笨鸟到菜鸟之(十五)Html基础积累总结(下)

     本文来自:曹胜欢博客专栏.转载请注明出处:http://blog.csdn.net/csh624366188 一:表格 1.表格的基本语法 <table>...</table> ...

  8. javascript 阻止事件冒泡 cancelBubble

    javascript简单的阻止事件冒泡,可以使用事件的cancelBubble方法为true: html部分 <button id="btn1">点击显示div< ...

  9. 织梦CMS如何在首页调用指定的文章 idlist

    在网站首页调用站内新闻是必不可少的,但是有的时候不能根据自己的需要来调用指定的文章,想要调用自己指定的文章还要做一些修改. 在网站中调用指定文章可以使用织梦默认的标签idlist,在调用的时候使用以下 ...

  10. 跳转到AppStore 的不同位置办法

    程序跳转到appstore中指定的应用 1.进入appstore中指定的应用NSString *str = [NSString stringWithFormat:                    ...