题目大意:给你一个n*n的格子的棋盘,每个格子里面有一个非负数。 
从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和最大。

解题思路:最大点权独立集,关键是怎么建图了,我们可以采用染色的思想对这张图进行染色,然后分成两个点集 
假设将第一个格子染成白色,然后将它相邻的格子染成相反的颜色黑色,以此类推,这样就可以将一张图分成染成黑白两种颜色的点集了 
然后就是连边了,连边的话,我们只考虑白色格子的连向黑色格子的,因为两者之间是相对的,所以只需要取一条就好了 
这样图就建好了 
最大独立集就是:总权值-最小割了(最小割就是最小点权覆盖了)

最小割即最大流

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<queue>
using namespace std;
int n,a[][];
#define MAXN 500
#define MAXE 1100000
#define INF 0x7fffffff
int ne,nv,s,t;
int size,net[MAXN];
struct EDGE{
int v,next;
int cap;
int flow;
}edge[MAXE]; void init(){
size=;
memset(net,-,sizeof(net));
}
void add(int u,int v,int cap){
//cout<<u<<" "<<v<<" "<<cap<<endl;
ne++;
edge[size].v = v;
edge[size].cap = cap;
edge[size].flow = ;
edge[size].next = net[u];
net[u] = size;
++size; edge[size].v = u;
edge[size].cap = ;
edge[size].flow = ;
edge[size].next = net[v];
net[v] = size;
++size;
} int gap[MAXN];//gap优化
int dist[MAXN];//距离标号
int pre[MAXN];//前驱
int curedge[MAXN];//当前弧 int ISAP(){
int cur_flow,u,temp,neck,i;
int max_flow;
memset(gap,,sizeof(gap));
memset(pre,-,sizeof(pre));
memset(dist,,sizeof(dist));
for(i=;i<=nv;i++) curedge[i]=net[i];//将当前弧初始话成邻接表的第一条边
gap[nv]=nv;
max_flow=;
u=s;
while(dist[s]<nv){
if(u==t){//找到一条增广路
cur_flow=INF;
for(i=s;i!=t;i=edge[curedge[i]].v){//沿着增广路找到最小增广流量
if(cur_flow>edge[curedge[i]].cap){
neck=i;
cur_flow=edge[curedge[i]].cap;
}
}
for(i=s;i!=t;i=edge[curedge[i]].v){//更新
temp=curedge[i];
edge[temp].cap-=cur_flow;
edge[temp].flow+=cur_flow;
temp^=;
edge[temp].cap+=cur_flow;
edge[temp].flow-=cur_flow;
}
max_flow+=cur_flow;
u=neck;//下次直接从关键边的u开始新一轮的增广
}
for(i=curedge[u];i!=-;i=edge[i].next)//找到一条允许弧
if(edge[i].cap>&&dist[u]==dist[edge[i].v]+)
break;
if(i!=-){//如果找到 将u指向v
curedge[u]=i;
pre[edge[i].v]=u;
u=edge[i].v;
}
else{//找不到
if(==--gap[dist[u]]) break;//出现断层
curedge[u] = net[u];//把当前弧重新设为邻接表中满足要求的第一条弧
for(temp=nv,i=net[u];i!=-;i=edge[i].next)
if(edge[i].cap > )
temp=temp<dist[edge[i].v]?temp:dist[edge[i].v];
dist[u]=temp+;//将这个点的距离标号设为由它出发的所有弧的终点的距离标号的最小值加1
++gap[dist[u]];
if(u!=s)u=pre[u];
}
}
//cout<<max_flow<<endl;
return max_flow;
}
int main()
{
while (~scanf("%d",&n))
{
init();
int i,j,sum=;
for (i=;i<=n;i++)
for (j=;j<=n;j++) scanf("%d",&a[i][j]),sum+=a[i][j];
ne=;
nv=n*n+;
s=;
t=n*n+;
for (i=;i<=n;i++)
for (j=;j<=n;j++)
if ((i+j)&) add(n*(i-)+j+,n*n+,a[i][j]); else
{
add(,n*(i-)+j+,a[i][j]);
if (i>) add(n*(i-)+j+,n*(i-)+j+,(<<)-);
if (i<n) add(n*(i-)+j+,n*i+j+,(<<)-);
if (j>) add(n*(i-)+j+,n*(i-)+j,(<<)-);
if (j<n) add(n*(i-)+j+,n*(i-)+j+,(<<)-);
}
//cout<<nv<<" "<<ne<<endl;
printf("%d\n",sum-ISAP());
}
return ;
}

HDU1565 方格取数1(构图+网络流最大独立集合)的更多相关文章

  1. HDU1565 方格取数(1) —— 状压DP or 插头DP(轮廓线更新) or 二分图点带权最大独立集(最小割最大流)

    题目链接:https://vjudge.net/problem/HDU-1565 方格取数(1) Time Limit: 10000/5000 MS (Java/Others)    Memory L ...

  2. Libre 6007 「网络流 24 题」方格取数 / Luogu 2774 方格取数问题 (网络流,最大流)

    Libre 6007 「网络流 24 题」方格取数 / Luogu 2774 方格取数问题 (网络流,最大流) Description 在一个有 m*n 个方格的棋盘中,每个方格中有一个正整数.现要从 ...

  3. HDU-1565 方格取数(1)

    http://acm.hdu.edu.cn/showproblem.php?pid=1565 方格取数(1) Time Limit: 10000/5000 MS (Java/Others)    Me ...

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

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

  5. HDU1565 方格取数 &&uva 11270 轮廓线DP

    方格取数(1) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Su ...

  6. Hdu-1565 方格取数(1) (状态压缩dp入门题

    方格取数(1) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total S ...

  7. HLG 2163 方格取数 (最大网络流)

    题目链接:  m=ProblemSet&a=showProblem&problem_id=2163">点击打开链接 Description : 给你一个n*n的格子的棋 ...

  8. HDU1565 方格取数(1)

    Problem Description 给你一个n*n的格子的棋盘,每个格子里面有一个非负数.从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数 ...

  9. HDU1565 方格取数(1)(状态压缩dp)

    题目链接. 分析: 说这题是状态压缩dp,其实不是,怎么说呢,题目数据太水了,所以就过了.手动输入n=20的情况,超时.正解是网络流,不太会. A这题时有个细节错了,是dp[i][j]还是dp[i][ ...

随机推荐

  1. 修复mysql的表

    数据损坏原因 MySQL表损坏一般是数据损坏,引起损坏的原因可能是由于磁盘损坏.系统崩溃或者MySQL服务器被崩溃等外部原因.例如有人使用kill -9终止进程,导致MySQL进程未能正常关闭,那么就 ...

  2. Visual Studio Code 扩展工具集,记录

    编码 提高效率及校验 Auto Close Tag 自动闭合标签 Auto Rename Tag 自动更改HTML/XML标签,不需要再进行二次修改,减少50%的工作量! Path Intellise ...

  3. 关于ListView的注意点

    解决ListView的一些常见问题: 1.listview在拖动的时候背景图片消失变成黑色背景,等到拖动完毕我们自己的背景图片才显示出来 解决:在XML中加入 android:scrollingCac ...

  4. [Qt Creator 快速入门] 第3章 窗口部件

    从这一章开始正式接触Qt的窗口部件.在第2章曾看到 Qt Creator 提供的默认基类只有 QMainWindow.QWidget 和 QDialog 这3种.QMainWindow 是带有菜单栏和 ...

  5. 51nod1265判断四点共面

    1265 四点共面 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 给出三维空间上的四个点(点与点的位置均不相同),判断这4个点是否在同一个平面内(4点共 ...

  6. 257 Binary Tree Paths 二叉树的所有路径

    给定一个二叉树,返回从根节点到叶节点的所有路径.例如,给定以下二叉树:   1 /   \2     3 \  5所有根到叶路径是:["1->2->5", " ...

  7. Java 8 (2) 使用Lambda表达式

    什么是Lambda? 可以把Lambda表达式理解为 简洁的表示可传递的匿名函数的一种方式:它没有名称,但它有参数列表.函数主体.返回类型,可能还有一个可以抛出的异常列表. 使用Lambda可以让你更 ...

  8. [ NOI 2001 ] 方程的解数

    \(\\\) \(Description\) 已知一个 \(N\) 元高次方程: \[ k_1x_1^{p_1}+k_2x_2^{p_2}+...+k_nx_n^{p_n}=0 \] 要求所有的 \( ...

  9. Python学习笔记之默认参数

    函数定义时 参数定义的顺序必须是:必选参数.默认参数.可变参数和关键字参数. def test(a,b,c=1,*d,**e) pass

  10. 模式匹配第四弹:if case,guard case,for case

    2016-06-06 7388 作者:Olivier Halligon,原文链接,原文日期:2016-05-16 译者:walkingway:校对:Cee:定稿:numbbbbb 现在我们来重新回顾下 ...