题目大意:

给你一个n*n的格子的棋盘,每个格子里面有一个非负数。

从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和最大。

初看:

没想法中..Orz, 万物皆网络流??

如何构图??如何构图??

以什么为容量? 格子里的数吗?

点呢?

超级源是什么??超级汇是什么??

这特么是网络流??

呜。。好想看题解。。好难。。

再想会。。

拆点?

或者网络流只是辅助 主算法其实是搜索?

想到7点就看题解了。。

最后的脑洞乱开

超级源向所有点连一条容量为格子内数值的边。

然后考虑消除相邻边的影响 能选某个点,必须周围4个都没有被选择

用网络流怎么实现这种操作?感觉不可能。。

好烦,7点了(其实还差5分钟),看题解了。

卧槽

原来是最小割和最大点权独立集

先来补补最大点权独立集的基础知识:

http://yzmduncan.iteye.com/blog/1149057

看完后还有一下难点:为何可以变成二分图?

鸟神告诉我 黑白染色

这又涉及到二分图的定义及判断问题(顺便翻下离散数学复习一下..然而离散并没有..去网上看看..)

---------------------------------------------------------------------------------------------------------------------------------------------------------

二分图又称作二部图,是图论中的一种特殊模型。 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图。

无向图G为二分图的充分必要条件是,G至少有两个顶点,且其所有回路的长度均为偶数。回路就是环路,也就是判断是否存在奇数环。

判断二分图方法:

    用染色法,把图中的点染成黑色和白色。

    首先取一个点染成白色,然后将其相邻的点染成黑色,如果发现有相邻且同色的点,那么就退出,可知这个图并非二分图。

----------------------------------------------------------------------------------------------------------------------------------------------------------------------

所以显然可知 该图是二分图,且黑白染色后,黑白即为二分图两端。

求二分图的最大点权独立集

--------------------------------------------------------------------------------------

开始写代码...然后写题解...

s连向白点 流量为白点的值

白点连黑点 流量无穷大

黑点连t   流量黑点的值

求最大流maxflow

ans=sum-maxflow

证明在上面

代码:

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#define oo 0x13131313
using namespace std;
const int MAXN=400+5;
const int MAXM=10000;
const int INF=0x3f3f3f3f;
int s,t;
struct Edge
{
int to,next,cap,flow;
void get(int a,int b,int c,int d)
{
to=a;next=b;cap=c;flow=d;
}
}edge[MAXM];
int tol;
int head[MAXN];
int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN];
void init()
{
tol=0;
memset(head,-1,sizeof(head));
}
//单向图三个参数,无向图四个参数
void addedge(int u,int v,int w,int rw=0)
{
edge[tol].get(v,head[u],w,0);head[u]=tol++;
edge[tol].get(u,head[v],rw,0);head[v]=tol++;
}
int sap(int start,int end,int N)
{
memset(gap,0,sizeof(gap));
memset(dep,0,sizeof(dep));
memcpy(cur,head,sizeof(head));
int u=start;
pre[u]=-1;
gap[0]=N;
int ans=0;
while(dep[start]<N)
{
if(u==end)
{
int Min=INF;
for(int i=pre[u];i!=-1;i=pre[edge[i^1].to])
if(Min>edge[i].cap-edge[i].flow)
Min=edge[i].cap-edge[i].flow;
for(int i=pre[u];i!=-1;i=pre[edge[i^1].to])
{
edge[i].flow+=Min;
edge[i^1].flow-=Min;
}
u = start;
ans+=Min;
continue;
}
bool flag=false;
int v;
for(int i=cur[u];i !=-1;i=edge[i].next)
{
v=edge[i].to;
if(edge[i].cap-edge[i].flow&&dep[v]+1==dep[u])
{
flag=true;
cur[u]=pre[v]=i;
break;
}
}
if(flag)
{
u=v;
continue;
}
int Min=N;
for(int i=head[u];i!=-1;i=edge[i].next)
if(edge[i].cap-edge[i].flow&&dep[edge[i].to]<Min)
{
Min=dep[edge[i].to];
cur[u]=i;
}
gap[dep[u]]--;
if(!gap[dep[u]]) return ans;
dep[u]=Min+1;
gap[dep[u]]++;
if(u!=start) u=edge[pre[u]^1].to;
}
return ans;
}
//new type
void INIT()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
}
int n;
int sum;
int map[30][30];
int T[30][30];
int fx[4]={1,-1,0,0},fy[4]={0,0,1,-1};
void input()
{
init();
sum=0;
memset(T,0,sizeof(T));
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
scanf("%d",&map[i][j]);
T[i][j]=(i-1)*n+j;
sum+=map[i][j];
}
}
void solve()
{
s=0;t=n*n+1;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if((i+j)%2==0)
{
addedge(s,T[i][j],map[i][j]);
for(int k=0;k<4;k++)
{
if(T[i+fx[k]][j+fy[k]]!=0)
addedge(T[i][j],T[i+fx[k]][j+fy[k]],INF);
}
}
else
{
addedge(T[i][j],t,map[i][j]);
}
} }
int main()
{
// INIT();
while(cin>>n)
{
int ans;
input();
solve();
ans=sap(s,t,n*n+2);
printf("%d\n",sum-ans);
}
}

【最大点权独立集】【HDU1565】【方格取数】的更多相关文章

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

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

  2. HDU1565 方格取数1(构图+网络流最大独立集合)

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

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

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

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

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

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

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

  6. HDU1565 方格取数(1)

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

  7. HDU1565方格取数

    典型的状态压缩DP问题.第i行的取法只受到第i-1行的影响.首先每一行的取法要相容(不能有两个相邻),然后相邻行之间也要相容.将每一个格子看做两种状态,1表示取,0表示不取.这样每一行就是一个01串, ...

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

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

  9. hdu1569 方格取数(2) 最大点权独立集=总权和-最小点权覆盖集 (最小点权覆盖集=最小割=最大流)

    /** 转自:http://blog.csdn.net/u011498819/article/details/20772147 题目:hdu1569 方格取数(2) 链接:https://vjudge ...

  10. hdu1569 方格取数 求最大点权独立集

    题意:一个方格n*m,取出一些点,要求两两不相邻,求最大和.思路:建图,相邻的点有一条边,则建立了一个二分图,求最大点权独立集(所取点两两无公共边,权值和最大),问题转化为求总权和-最小点权覆盖集(点 ...

随机推荐

  1. rsync常用参数详解

    rsync常用参数详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在linux中,一切皆是文件,包括你的终端,硬件设备信息,目录,内核文件等等.所以工作中我们难免会遇到拷贝文件 ...

  2. Hibernate中save、saveorupdate、persist方法的区别

    在Hibernate中,save().saveOrUpdate()和persist()都是用于将对象保存到数据库中的方法,但其中有些细微的差别.例如,save()只能INSERT记录,但是saveOr ...

  3. Longest Palindromic Substring-----最长回文子串

    首先讲讲什么是回文, 看看Wiki是怎么说的:回文,亦称回环,是正读反读都能读通的句子.亦有将文字排列成圆圈者,是一种修辞方式和文字游戏.回环运用得当.能够表现两种事物或现象相互依靠或排斥的关系, 比 ...

  4. Web安全技术(3)-浏览器的跨域访问

    http://www.blogjava.net/linli/archive/2015/04/22/424584.html 一.浏览器介绍 对于Web应用来说,浏览器是最重要的客户端. 目前浏览器五花八 ...

  5. Android 关于屏幕适配

    android屏幕适配详解 官方地址:http://developer.android.com/guide/practices/screens_support.html 转自:http://www.c ...

  6. UVA 140 Bandwidth

    题意: 给出一个n个节点的图G,和一个节点的排列,定义节点i的带宽为i和相邻节点在排列中的最远距离,而所有带宽的最大值就是图的带宽,求让图的带宽最小的排列. 分析: 列出所有可能的排列,记录当前找到的 ...

  7. (转)(VS2013 )由于应用程序配置不正确,程序未能启动”--原因及解决方法

    今天把别人的程序拿过来编译时通过,但是运行的时候,提示:由于应用程序配置不正确,程序未能启动 搜了一下,各种方法.最终通过下面的方法解决的. 项目--->配置属性---->链接器----& ...

  8. 翻译题(map使用)

    What Are You Talking About 点我 Problem Description Ignatius is so lucky that he met a Martian yesterd ...

  9. linux----用户与whoami

    linux中的su 命令可以完成用户切换:如我们先由root切换到mysql用户可以这样做su - mysql whoami #这个时候linux会打印出mysql who am i #这个时候lin ...

  10. linux case 语句

    #!/bin/bash #$ 表示脚本名 #$n 表示第n个参数(n>) in ") echo '--=> A' ;; ") echo '--=> B' ;; * ...