HDU1565 方格取数1(构图+网络流最大独立集合)
题目大意:给你一个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(构图+网络流最大独立集合)的更多相关文章
- HDU1565 方格取数(1) —— 状压DP or 插头DP(轮廓线更新) or 二分图点带权最大独立集(最小割最大流)
题目链接:https://vjudge.net/problem/HDU-1565 方格取数(1) Time Limit: 10000/5000 MS (Java/Others) Memory L ...
- Libre 6007 「网络流 24 题」方格取数 / Luogu 2774 方格取数问题 (网络流,最大流)
Libre 6007 「网络流 24 题」方格取数 / Luogu 2774 方格取数问题 (网络流,最大流) Description 在一个有 m*n 个方格的棋盘中,每个方格中有一个正整数.现要从 ...
- HDU-1565 方格取数(1)
http://acm.hdu.edu.cn/showproblem.php?pid=1565 方格取数(1) Time Limit: 10000/5000 MS (Java/Others) Me ...
- P2774 方格取数问题(网络流)
P2774 方格取数问题 emm........仔细一看,这不是最大权闭合子图的题吗! 取一个点$(x,y)$,限制条件是同时取$(x,y+1),(x,y-1),(x+1,y),(x-1,y)$,只不 ...
- HDU1565 方格取数 &&uva 11270 轮廓线DP
方格取数(1) Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Su ...
- Hdu-1565 方格取数(1) (状态压缩dp入门题
方格取数(1) Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total S ...
- HLG 2163 方格取数 (最大网络流)
题目链接: m=ProblemSet&a=showProblem&problem_id=2163">点击打开链接 Description : 给你一个n*n的格子的棋 ...
- HDU1565 方格取数(1)
Problem Description 给你一个n*n的格子的棋盘,每个格子里面有一个非负数.从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数 ...
- HDU1565 方格取数(1)(状态压缩dp)
题目链接. 分析: 说这题是状态压缩dp,其实不是,怎么说呢,题目数据太水了,所以就过了.手动输入n=20的情况,超时.正解是网络流,不太会. A这题时有个细节错了,是dp[i][j]还是dp[i][ ...
随机推荐
- magento getUrl函数跳转admin模块问题
在用以下代码时,跳转后的url里面会是空的,即没有admin这个值 $this->getUrl('admin/catalog_product/edit', array('id' => $c ...
- java简单打印金字塔(案例)
学习编程语言,打印简单的金字塔是基础的案例,在这里就简单的写了个案例,希望能帮助到各位 代码 效果 class kinTa{ public static void main(String[] ...
- [ Nowcoder Contest 167 #C ] 部分和
\(\\\) \(Description\) 给出一个长度为\(N\)的数组\(A[i]\),保证\(N\)为 \(2\) 的整次幂. 对于每个 \(i\ (i\in [0,N))\)求所有满足\(( ...
- CF861B Which floor?
思路: 暴力枚举. 实现: #include <bits/stdc++.h> using namespace std; int n, m, x, y; bool check(int x, ...
- python实现qq机器人qqbot
title: python实现qq机器人qqbot tags: python date: 2018-6-1 10:19:00 --- 以下内容为转载 一.介绍 qqbot 是一个用 python 实现 ...
- oracle dos命令
1.无账户密码登录数据库:sqlplus/nolog 后面不能加分号,否则不能识别 2.登录数据库:sqlplus 3.在sql下测试连接性:conn oracle_name/oracle_passw ...
- 【转载】 python sort、sorted高级排序技巧
这篇文章主要介绍了python sort.sorted高级排序技巧,本文讲解了基础排序.升序和降序.排序的稳定性和复杂排序.cmp函数排序法等内容,需要的朋友可以参考下 Python list内置so ...
- 【转】Go语言入门教程(一)Linux下安装Go
说明 系统是Ubuntu. 关于安装 下载安装包 当前官方下载地址是https://golang.org/dl/,如果不能访问,请自行FQ,FQ是技术工作者的必备技能. 安装 tar -xzvf go ...
- jdbcTemplate传参使用Map或List
List传参方式 举个例子 sql = "select * from table where id=? and param=?": sql中的参数要用?形式,然后使用list.ad ...
- Script:shell脚本生成随机字符串
#!/bin/bash # bash generate random alphanumeric string # # bash generate random character alphanumer ...