hdu 1569 方格取数(2)--最大点权独立集-->最大流
2012-11-05 13:51
239 查看
/* 二分图最小点覆盖和最大独立集都可以转化为最大匹配求解。在这个基础上,把每个点赋予一个非负的权值,这两个问题就转化为:二分图最小点权覆盖和二分图最大点权独立集。 二分图最小点权覆盖 从x或者y集合中选取一些点,使这些点覆盖所有的边,并且选出来的点的权值尽可能小。 建模: 原二分图中的边(u,v)替换为容量为INF的有向边(u,v),设立源点s和汇点t,将s和x集合中的点相连,容量为该点的权值; 将y中的点同t相连,容量为该点的权值。在新图上求最大流,最大流量即为最小点权覆盖的权值和。 二分图最大点权独立集 在二分图中找到权值和最大的点集,使得它们之间两两没有边。其实它是最小点权覆盖的对偶问题。答案=总权值-最小点覆盖集。具体证明参考胡波涛的论文。 最大流=最小割=最小点权覆盖集=sum-最大点权独立集 题意:一个m*n的棋盘,每个格子都有一个权值,从中取出某些数,使得任意两个数所在的格子没有公共边,并且所取去出的数和最大。求这个最大的值。 解: 将格子染色成二分图,显然是求二分图的最大点权独立集。将问题转化为二分图最小点权覆盖来求解,最终结果=总权和-最大流。 */ #include<stdio.h> #include<string.h> #define inf 0x7fffffff struct edge//边 { int u,v,f,next,b,c;//边的 前节点 后节点 可用流 下条边的编号 原来边上流的上下界 }e[400000]; int head[3000],in[1400],out[1400],m,s,t,ss,tt,yong,indexx[400000],ind; int n,map[25][25],sum; void adde(int from,int to,int xia,int shang)//加边 {//加边 e[yong].u=from,e[yong].v=to,e[yong].f=shang-xia,e[yong].b=xia,e[yong].c=shang; e[yong].next=head[from],head[from]=yong++; //同时加它的退边 e[yong].u=to,e[yong].v=from,e[yong].f=0,e[yong].b=xia,e[yong].c=shang; e[yong].next=head[to],head[to]=yong++; } int d[3000],num[3000]; int min(int a,int b){return a<b?a:b;} int sap_gap(int u,int f,int s,int t)//递归sap { if(u==t) return f; int i,v,mind=t,last=f,cost; for(i=head[u];i!=-1;i=e[i].next) { v=e[i].v; int flow=e[i].f; if(flow>0)//参考模版写的时候把flow写成了f { if(d[u]==d[v]+1) { cost=sap_gap(v,min(last,flow),s,t); e[i].f-=cost; e[i^1].f+=cost; last-=cost; if(d[s]>=t+1) return f-last; if(last==0) break; } if(d[v]<mind) mind=d[v]; } } if(last==f) { --num[d[u]]; if(num[d[u]]==0) d[s]=t+1; d[u]=mind+1; ++num[d[u]]; } return f-last; } int max_f(int s,int t)//调用递归sap { int f=0; memset(d,0,sizeof(d)); memset(num,0,sizeof(num)); for(num[s]=t+1;d[s]<t+1;) f+=sap_gap(s,inf,s,t); return f; } int id(int i,int j) { return i*m+j; } int main() { int i,j; while(scanf("%d%d",&n,&m)!=EOF) { /* n*m个点 0--n*m-1 s=n*n t=s+1 */ sum=0; memset(head,-1,sizeof(head)); s=n*m,t=s+1; for(i=0;i<n;i++) { for(j=0;j<m;j++) { scanf("%d",&map[i][j]); sum+=map[i][j]; if((i+j)%2) { adde(s,id(i,j),0,map[i][j]); if(i>0) adde(id(i,j),id(i-1,j),0,inf); if(i<(n-1)) adde(id(i,j),id(i+1,j),0,inf); if(j>0) adde(id(i,j),id(i,j-1),0,inf); if(j<(m-1)) adde(id(i,j),id(i,j+1),0,inf); } else { adde(id(i,j),t,0,map[i][j]); } } } printf("%d\n",sum-max_f(s,t)); } return 0; }
相关文章推荐
- HDU 1569 方格取数(2)(最大流最小割の最大权独立集)
- 【网络流第五弹】最大点权独立集 ——HDU 1569 方格取数(2)
- HDU 1569 - 方格取数(2) 二分图最大点权独立集(构图最大流解)
- HDU 1569 方格取数(2) (二分图的最大点权独立集)
- HDU 1565 1569 方格取数(最大点权独立集)
- hdu1569 方格取数(2) 最大点权独立集=总权和-最小点权覆盖集 (最小点权覆盖集=最小割=最大流)
- HDU 1569 方格取数(2)(最大点权独立集)
- hdu - 1565 方格取数(1) && 1569 方格取数(2) (最大点权独立集)
- HDU 1569 方格取数(2)(最大点权独立集)
- hdoj 1569 方格取数 【最大点权独立集->最大流】
- Hdu 1569 方格取数(2) (网络流最大点权独立集)
- hdu 1569 方格取数 最大点权独立集(hdu 1565)
- 独立最小【网络流第五弹】最大点权独立集 ——HDU 1569 方格取数(2)
- HDU 1569 方格取数(2) 黑白染色+最大点独立集(sap)
- HDU 1565 1569 方格取数(最大点权独立集)
- 方格取数(2) HDU - 1569(二分图最大点权独立集)
- hdu 1565+hdu 1569(最大点权独立集)
- 二分图带权最大独立集 网络流解决 hdu 1569
- HDU 1565 方格取数(1)(最大点权独立集)
- HDU 1569 方格取数(2) 最大点权独立集