要选出一些点,这些点之间没有相邻边且要求权值之和最大,求这个权值

分析:二分图带权最大独立集.

用最大流最小割定理求解.其建图思路是:将所有格点编号,奇数视作X部,偶数视作Y部,建立源点S和汇点T, S向X部的点建边,Y部向T建边,容量为该点权值.

相邻的一对点(肯定是一奇一偶),由X中的点向Y中的点建边,容量为正无穷.

最后跑出最大流,|带权最大独立集| = |点权之和| - |最小割| = |点权之和| - |最大流|

#include<iostream>
#include<cstring>
#include<stdio.h>
#include<algorithm>
#include<string>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN=3010;//点数的最大值
const int MAXM=400010;//边数的最大值
#define captype int struct SAP_MaxFlow{
struct Edge{
int from,to,next;
captype cap;
}edges[MAXM];
int tot,head[MAXN];
int gap[MAXN];
int dis[MAXN];
int cur[MAXN];
int pre[MAXN]; void init(){
tot=0;
memset(head,-1,sizeof(head));
}
void AddEdge(int u,int v,captype c,captype rc=0){
edges[tot] = (Edge){u,v,head[u],c}; head[u]=tot++;
edges[tot] = (Edge){v,u,head[v],rc}; head[v]=tot++;
}
captype maxFlow_sap(int sNode,int eNode, int n){//n是包括源点和汇点的总点个数,这个一定要注意
memset(gap,0,sizeof(gap));
memset(dis,0,sizeof(dis));
memcpy(cur,head,sizeof(head));
pre[sNode] = -1;
gap[0]=n;
captype ans=0;
int u=sNode;
while(dis[sNode]<n){
if(u==eNode){
captype Min=INF ;
int inser;
for(int i=pre[u]; i!=-1; i=pre[edges[i^1].to])
if(Min>edges[i].cap){
Min=edges[i].cap;
inser=i;
}
for(int i=pre[u]; i!=-1; i=pre[edges[i^1].to]){
edges[i].cap-=Min;
edges[i^1].cap+=Min;
}
ans+=Min;
u=edges[inser^1].to;
continue;
}
bool flag = false;
int v;
for(int i=cur[u]; i!=-1; i=edges[i].next){
v=edges[i].to;
if(edges[i].cap>0 && dis[u]==dis[v]+1){
flag=true;
cur[u]=pre[v]=i;
break;
}
}
if(flag){
u=v;
continue;
}
int Mind= n;
for(int i=head[u]; i!=-1; i=edges[i].next)
if(edges[i].cap>0 && Mind>dis[edges[i].to]){
Mind=dis[edges[i].to];
cur[u]=i;
}
gap[dis[u]]--;
if(gap[dis[u]]==0) return ans;
dis[u]=Mind+1;
gap[dis[u]]++;
if(u!=sNode) u=edges[pre[u]^1].to; //退一条边
}
return ans;
}
}F; int G[55][55];
int dir[4][2] = {1,0,-1,0,0,1,0,-1}; int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int N,M;
int u,v,tmp;
while(scanf("%d %d",&N, &M)==2){
int S = 0,T = N*M+1;
int sum =0;
F.init();
for(int i=1;i<=N;++i){
for(int j=1;j<=M;++j){
scanf("%d",&tmp);
G[i][j] = tmp;
sum+=tmp;
}
}
for(int i=1;i<=N;++i){
for(int j=1;j<=M;++j){
int id = (i-1)*M +j;
if((i+j)&1){
F.AddEdge(S,id,G[i][j]);
for(int k=0;k<4;++k){
int nx = i+ dir[k][0];
int ny = j+ dir[k][1];
if(nx<1 || nx>N || ny<1 ||ny>M) continue;
int nid = (nx-1)*M + ny;
F.AddEdge(id,nid,INF);
}
}
else{
F.AddEdge((i-1)*M+j,T,G[i][j]);
}
}
}
int flow = F.maxFlow_sap(S,T,T+1);
int res = sum - flow;
printf("%d\n",res);
}
return 0;
}

最新文章

  1. 【搬砖】安卓入门(4)- Java开发编程基础--数组
  2. 总结的js性能优化方面的小知识
  3. Java File 常用操作回顾
  4. Github上传代码菜鸟超详细教程【转】
  5. Mybatis 和 Spring配置
  6. 转!!各种数据库的jdbc驱动下载及连接方式
  7. Base
  8. 在Android中显示GIF动画
  9. 使用IntelliJ IDEA(PHPStorm)和xdebug在firefox、chrome中远程调试PHP
  10. [LeetCode] Find Duplicate Subtrees 寻找重复树
  11. 目标检测之YOLO V2 V3
  12. 汇编入门——使用DOSBox写一个HelloWorld以及相关软件安装
  13. CAMediaTiming`协议(9.1 图层时间)
  14. 转化为json方式函数
  15. filter vs servlet
  16. 信号(Django信号、Flask信号、Scrapy信号)
  17. 细说PHP7
  18. JS原生隐藏显示图片,点击切换图片的效果
  19. Android测试:从零开始1——简介
  20. Hyperledger Fabric系统架构

热门文章

  1. MySQL单列索引和组合索引的选择效率与explain分析
  2. 在ASP.NET MVC 3 中自定义AuthorizeAttribute时需要注意的页面缓存问题
  3. $_SERVER,IP,域名常用方法
  4. 【H.264/AVC视频编解码技术具体解释】十三、熵编码算法(4):H.264使用CAVLC解析宏块的残差数据
  5. 编程之美 set 10 队列中取最大值操作问题
  6. kotlin正式由Goole公布为Android的最新开发语言
  7. 构建API
  8. 【BZOJ3809/3236】Gty的二逼妹子序列 [Ahoi2013]作业 莫队算法+分块
  9. NIO中几个非常重要的技术点
  10. Array.prototype.filter(Boolean)