HDU 1565 方格取数(1) 【最大流.最大点权独立集】

Problem Description
给你一个n*n的格子的棋盘,每个格子里面有一个非负数。
从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和最大。
Input
包括多个测试实例,每个测试实例包括一个整数n 和n*n个非负数(n<=20)
Output
对于每个测试实例,输出可能取得的最大的和
Sample Input
3
75 15 21
75 15 28
34 70 5
Sample Output
188

预备知识:

点覆盖集:无向图G的一个点集,使得该图中所有边都至少有一个端点在该集合内。
最小点权覆盖集:在带点权无向图G中,点权之和最小的覆盖集。
点独立集:无向图G的一个点集,使得任两个在该集合中的点在原图中都不相邻。
最大点权独立集:在带权无向图G中,点权之和最大的独立集。


 // 定理:
 // 1. 最小点权覆盖集=最小割=最大流
 // 2. 最大点权独立集=总权-最小点权覆盖集
 // 解题:
 // 1. 先染色,取一个点染白色,和它相邻的点染黑色
 // 2. 每个白点向它相邻的黑点连一条边,容量为 inf (无穷大)
 // 3. 增加源点S,向每一个白色点连一条边,容量为白点的权
 // 4. 增加汇点T,每个黑点向T连一条边,容量为黑点的权
 // 5. 求MaxWVIS = TotalFlow - MaxFlow

 

以下摘自网络流24题解析

【建模分析】
这是一个二分图最大点权独立集问题,就是找出图中一些点,使得这些点之间没有边相连,这些点的权值之和最大。
独立集与覆盖集是互补的,求最大点权独立集可以转化为求最小点权覆盖集(最小点权支配集)。
最小点权覆盖集问题可以转化为最小割问题解决。
结论:最大点权独立集 = 所有点权 - 最小点权覆盖集 = 所有点权 - 最小割集 = 所有点权 - 网络最大流。
对于一个网络,除去冗余点(不存在一条ST路径经过的点),每个顶点都在一个从S到T的路径上。
割的性质就是不存在从S到T的路径,简单割可以认为割边关联的非ST节点为割点,而在二分图网络流模型中每个点必关联到一个割点(否则一定还有增广路,当前割不成立),
所以一个割集对应了一个覆盖集(支配集)。最小点权覆盖集就是最小简单割,求最小简单割的建模方法就是把XY集合之间的变容量设为无穷大,此时的最小割就是最小简单割了。
code:

View Code
预备知识:

点覆盖集:无向图G的一个点集,使得该图中所有边都至少有一个端点在该集合内。
最小点权覆盖集:在带点权无向图G中,点权之和最小的覆盖集。
点独立集:无向图G的一个点集,使得任两个在该集合中的点在原图中都不相邻。
最大点权独立集:在带权无向图G中,点权之和最大的独立集。


// 定理:
// 1. 最小点权覆盖集=最小割=最大流
// 2. 最大点权独立集=总权-最小点权覆盖集
// 解题:
// 1. 先染色,取一个点染白色,和它相邻的点染黑色
// 2. 每个白点向它相邻的黑点连一条边,容量为 inf (无穷大)
// 3. 增加源点S,向每一个白色点连一条边,容量为白点的权
// 4. 增加汇点T,每个黑点向T连一条边,容量为黑点的权
// 5. 求MaxWVIS = TotalFlow - MaxFlow





以下摘自网络流24题解析

【建模分析】
这是一个二分图最大点权独立集问题,就是找出图中一些点,使得这些点之间没有边相连,这些点的权值之和最大。
独立集与覆盖集是互补的,求最大点权独立集可以转化为求最小点权覆盖集(最小点权支配集)。
最小点权覆盖集问题可以转化为最小割问题解决。
结论:最大点权独立集 = 所有点权 - 最小点权覆盖集 = 所有点权 - 最小割集 = 所有点权 - 网络最大流。
对于一个网络,除去冗余点(不存在一条ST路径经过的点),每个顶点都在一个从S到T的路径上。
割的性质就是不存在从S到T的路径,简单割可以认为割边关联的非ST节点为割点,而在二分图网络流模型中每个点必关联到一个割点(否则一定还有增广路,当前割不成立),
所以一个割集对应了一个覆盖集(支配集)。最小点权覆盖集就是最小简单割,求最小简单割的建模方法就是把XY集合之间的变容量设为无穷大,此时的最小割就是最小简单割了。
code:


#include<stdio.h>
#include<string.h>
#define min(a,b)(a)<(b)?(a):(b)
#define clr(x)memset(x,0,sizeof(x))
#define maxn 55
#define inf 9999999
int n,m,s,t,top;
int map[maxn][maxn];
int q[3000];
int flow[maxn][maxn];
int c[maxn][maxn];
int a[maxn];
int p[maxn];
void addedge(int ss,int ee,int w)
{
c[ss][ee]+=w;
}
int EK()
{
s=n*n; t=n*n+1;
int maxflow=0;
int u,v,front,rear;
clr(p);
for(;;)
{
clr(a);
a[s]=inf;
front=rear=0;
q[rear++]=s;
while(front<rear)
{
u=q[front];
front++;
for(v=0;v<=n*m+1;v++)
if(!a[v]&&c[u][v]>flow[u][v])
{
p[v]=u;
q[rear++]=v;
a[v]=min(a[u],c[u][v]-flow[u][v]);
}
}
if(a[t]==0) break;
for(u=t;u!=s;u=p[u])
{
flow[p[u]][u]+=a[t];
flow[u][p[u]]-=a[t];
}
maxflow+=a[t];
}
return maxflow;
}
int main()
{
int tot,i,j,t;
while(scanf("%d%d",&n,&m)!=EOF)
{
clr(flow); clr(c); clr(a);
tot=0;
for(i=0;i<n;i++)
for(j=0;j<m;j++)
{
scanf("%d",&t);
tot+=t;
if((i+j)%2) // whilte
{
addedge(n*m,i*n+j,t);
if(j+1<n) addedge(i*n+j,i*n+j+1,inf);
if(i+1<n) addedge(i*n+j,(i+1)*n+j,inf);
if(j-1>=0) addedge(i*n+j,i*n+j-1,inf);
if(i-1>=0) addedge(i*n+j,(i-1)*n+j,inf);
}
else // black
addedge(i*n+j,n*m+1,t);
}
printf("%d\n",tot-EK());
}
return 0;
}

 

posted @ 2012-03-15 00:59  'wind  阅读(226)  评论(0编辑  收藏  举报