转载:http://blog.csdn.net/cold__v__moon/article/details/7924269
/*
这道题和方格取数2相似,是在方格取数2的基础上的变形。 方格取数2解法:
由题意知对于每一个方格,有选与不选,显然是二分的最大独立集,先求最小点权覆盖(它的补集恰好
是最大点权独立集),对于任何一条可行流 s->u->v->t, 在求最大流或最小割的时候,在这3条边中
至少选一条,将u->v设为inf,u->v就不可能存在于最小割中,就只是2选1,如果s->u或v->t选为最小割
则表示u或v(u和v可同时被选)属于最小点权覆盖,所以最小割=最小点权覆盖,再求补集就是最大点权独立集。 这道题的变形:
先考虑的答案的补集(类似最小点权覆盖,但不是),和方格取数不同的是可以去相邻的格子但是要减去2*(G[i][j]&G[a][b]);
所以对于答案的补集就是加上2*(G[i][j]&G[a][b]),对于任何一条可行流 s->u->v->t, 当u->v为2*(G[i][j]&G[a][b]),就可以
表示同时选取u,v的情况,对于答案的必选点s->u就是不存在割的s->u为inf;
推荐学习胡伯涛《最小割模型在信息学竞赛中的应用》,其中对最小割的模型应用讲的很清楚
*/
#include <iostream>
#include <memory.h>
#include <stdio.h>
using namespace std;
const int maxn=55;
const int maxm=maxn*maxn;
const int inf=0x3fffffff;
int G[maxn][maxn];
bool f[maxn][maxn];
int head[maxm],dis[maxm],gap[maxm],cur[maxm],e,pre[maxm];
int dir[4][2]={0,1,0,-1,1,0,-1,0};
int source,sink;
struct
{
int t,next,w;
}edge[maxm*6];
void add(int a,int b,int c)
{
//printf("%d->%d %d\n",a,b,c);
edge[e].t=b;
edge[e].w=c;
edge[e].next=head[a];
head[a]=e++;
edge[e].t=a;
edge[e].w=0;
edge[e].next=head[b];
head[b]=e++;
}
int sap(int ncnt)
{
memset(dis,0,sizeof(dis));
memset(gap,0,sizeof(gap));
for(int i=0;i<=ncnt;i++)
cur[i]=head[i];
int u=pre[source]=source,maxflow=0,aug=inf;
gap[0]=ncnt;
//P();
while(dis[source]<ncnt)
{
loop: for(int &i=cur[u];i!=-1;i=edge[i].next)
{
//P();
int v=edge[i].t;
if(edge[i].w&&dis[u]==dis[v]+1)
{
aug=min(aug,edge[i].w);
pre[v]=u;
//printf("%d-> %d\n",u,v);
u=v;
if(v==sink)
{
maxflow+=aug;
for(u=pre[u];v!=source;v=u,u=pre[u])
{
edge[cur[u]].w-=aug;
edge[cur[u]^1].w+=aug;
//printf("d");
}
aug=inf;
}
goto loop;
}
}
int mindis=ncnt;
//P();
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].t;
if(edge[i].w&&mindis>dis[v])
{
//printf("s");
cur[u]=i;
mindis=dis[v];
}
} if(--gap[dis[u]]==0)
break;
gap[dis[u]=mindis+1]++;
u=pre[u]; } return maxflow;
}
int main()
{
int n,m,a,b,sum,k;
while(~scanf("%d%d%d",&n,&m,&k))
{
sum=0;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
scanf("%d",&G[i][j]);
sum+=G[i][j];
}
memset(f,false,sizeof(f));
for(int i=0;i<k;i++)
{
scanf("%d%d",&a,&b);
a--;
b--;
f[a][b]=true;
}
memset(head,-1,sizeof(head));
e=0;
source=n*m;
sink=n*m+1;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
if((i+j)%2==1)
{
add(source,i*m+j,f[i][j]?inf:G[i][j]);
for(int k=0;k<4;k++)
{
a=i+dir[k][0];
b=j+dir[k][1];
if(a>=0&&a<n&&b>=0&&b<m)
add(i*m+j,a*m+b,(G[i][j]&G[a][b])<<1);
}
}
else add(i*m+j,sink,f[i][j]?inf:G[i][j]);
printf("%d\n",sum-sap(n*m+2)); } return 0;
}

hdu 3657 最大点权独立集变形(方格取数的变形最小割,对于最小割建图很好的题)的更多相关文章

  1. hdu 3657最大点权独立集变形(方格取数变形)

    /* 分奇偶为二部图,s与奇建图,t与偶建图,权值为当前数的值,如果遇到必取的权值置为inf. 奇偶建边为相邻的权值为2*(x&y):所有数的值-最小点全覆盖. 置为inf意为不能割掉.奇偶边 ...

  2. hdu 4859 最大点权独立集的变形(方格取数的变形)

    /*刚开始不会写,最大点权独立集神马都不知道,在潘神的指导下终于做出来,灰常感谢ps: 和方格取数差不多奇偶建图,对于D必割点权为0,对于.必然不割点权为inf.然后和方格取数差不多的建图 .--.| ...

  3. HDU 1565 最大点权独立集

    首先要明白图论的几个定义: 点覆盖.最小点覆盖: 点覆盖集即一个点集,使得所有边至少有一个端点在集合里.或者说是“点” 覆盖了所有“边”.. 最小点覆盖(minimum vertex covering ...

  4. hdu 1565&&hdu 1569 (最大点权独立集)

    题目意思很明确就是选一些没有相连的数字,使和最大,建成二分图后求最大点权独立集,, #include<stdio.h> #include<string.h> const int ...

  5. 洛谷 - P2774 - 方格取数问题 - 二分图最大独立点集 - 最小割

    https://www.luogu.org/problemnew/show/P2774 把两个相邻的节点连边,这些边就是要方便最小割割断其他边存在的,容量无穷. 这种类似的问题的话,把二分图的一部分( ...

  6. HDU 1569 - 方格取数(2) - [最大点权独立集与最小点权覆盖集]

    嗯,这是关于最大点权独立集与最小点权覆盖集的姿势,很简单对吧,然后开始看题. 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1569 Time Limi ...

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

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

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

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

  9. HDU 1565 1569 方格取数(最大点权独立集)

    HDU 1565 1569 方格取数(最大点权独立集) 题目链接 题意:中文题 思路:最大点权独立集 = 总权值 - 最小割 = 总权值 - 最大流 那么原图周围不能连边,那么就能够分成黑白棋盘.源点 ...

随机推荐

  1. java 监听机制模拟(JButton按钮监听机制)

    一.概念 1.事件监听器 事件监听器就我个人的理解就是:被外部事件(键盘.鼠标)引发的程序,这段程序是被嵌入到事件源的类里面,它负责监听事件列表.而很多人把事件监听器理解成是实现EventListen ...

  2. 个人微信二次开发API接口

    通过这个API接口可以做什么? 通过我们提供的API接口您可以开发: 工作手机(如:X创,X码,XX管家等) 微信群讲课软件(如:讲课X师,一起X堂等) 微信社群管理软件(如:小X管家,微X助手等) ...

  3. Codeforces 792D

    题意:给定一棵拥有n个节点的满二叉树(即n==2^x-1),q个查询,每次给出一个节点的编号,再给出一个由L,R,U组成的字符串序列,依次表示向左子节点.右子节点.父节点移动,如果移动不合法,则忽略. ...

  4. UNIX环境高级编程--6

    系统数据文件和信息    数据文件都是ASCII文本文件,并且使用标准I/O库读这些文件,例如口令文件/etc/passwd和组文件/etc/group就是经常被多个程序频繁使用的两个文件.    口 ...

  5. 329 Longest Increasing Path in a Matrix 矩阵中的最长递增路径

    Given an integer matrix, find the length of the longest increasing path.From each cell, you can eith ...

  6. Java系列学习(十)-包与权限修饰符

    1.形式参数和返回值的问题 (1)形式参数: A:类名:需要该类的对象 B:抽象类名:需要改类的子类对象 C:接口名:需要该接口的实现对象 (2)返回值类型: A:类名:抽象类名:返回的是该类的对象 ...

  7. 最容易理解的CSS的position教程——十步图解CSS的position

    CSS的positon,我想做为一个Web制作者来说都有碰到过,但至于对其是否真正的了解呢?那我就不也说了,至少我自己并不非常的了解其内核的运行.今天在Learn CSS Positioning in ...

  8. 使用WindowBuilder设计Swing程序

    Swing程序表示Java的客户端窗体程序,除了通过手动编写代码的方式设计Swing程序之外,Eclipse中还提供了一种WindowBuilder工具,该工具是一种非常好用的Swing可视化开发工具 ...

  9. Beta Edition [ Group 1 ]

    DeltaFish Beta Edition 一.七月开发过程 小组会议 DeltaFish 校园物资共享平台 第八次小组会议 GITHUB https://github.com/DeltaFishS ...

  10. 【PostgreSQL-9.6.3】触发器实例

    1. 创建一个触发器,表中的行在任何时候被插入或更新时,当前用户名和时间也会被标记在该行中.并且它会检查雇员的姓名以及薪水. --创建测试表 CREATE TABLE emp ( empname te ...