转载: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. poj3737 UmBasketella 真正的三分

    之前用二分写三分的板子...现在正式写一个三分,但是也不难,就是把区间分为三段就行了.求二次函数的峰值,每次取大的区间就行了. 题干: 最近几天,人们总是设计出多功能的新东西.例如,您不仅可以使用手机 ...

  2. bzoj1833

    http://www.lydsy.com/JudgeOnline/problem.php?id=1833 2.5个小时就花在这上面了... 水到200题了...然并卵,天天做水题有什么前途... #i ...

  3. 使用display:flex;实现垂直水平居中

    body,div{margin:0px;padding:0px;} .flex-container{display:flex;height:300px;background-color:#ddd;ju ...

  4. Ruby   离奇方法

    send https://ref.xaio.jp/ruby/classes/object/send find https://ref.xaio.jp/ruby/classes/enumerable/f ...

  5. roundabout旋转幻灯

    jquery.roundabout.js文件/** * jQuery Roundabout - v2.4.2 * http://fredhq.com/projects/roundabout * * M ...

  6. 【转】关于Java基础你不得不会的34个问题

    1. 面向对象和面向过程的区别 面向过程 优点: 性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机.嵌入式开发.Linux/Unix等一般采用面向过程开发,性能是最重要的 ...

  7. 安卓中Canvas实现清屏效果

    可以在代码里面添加: paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); canvas.drawPaint(paint) ...

  8. BZOJ 4140 凸包+二进制分组

    思路: $(x_0-x)^2+(y_0-y)^2<=x^2+y^2$ $y>=(-x_0/y_0)x+(x_0^2+y_0^2)/2y0$ 这显然就是凸包了 以一个斜率不断向下(上)走   ...

  9. Jquery课堂上课了,第一节Jquery选择器$

    Jquery是优秀的Javascrīpt框架,$是jquery库的申明,它很不稳定(我就常遇上),换一种稳定的写法jQuery.noConflict();                   jQue ...

  10. js-消息对话框

    最近在某技术网站学习一些js(JavaScript)的课程,将笔记分享一下 消息对话框1. **alert **消息对话框,输出内容,可以是字符串或变量,与document.write 相似   va ...