网络流 方格取数类型题的总结 + HDU3820

2024-05-10 12:08

本文主要是介绍网络流 方格取数类型题的总结 + HDU3820,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目分析:最小割!

方格取数一类问题!

现在就这一类做一个小结吧。。。。

1.首先是方格内有固定的权值,可以取不相邻的数,问怎样取使权值最大。

这样我们奇偶建图,源点掌管奇属性点,汇点掌管偶属性点,然后相邻的两点建边容量无穷大,源汇向自己掌管的点建边,容量为权值。这样建图的意义在于,如果某一条边被割掉,那么久说明这个点被抛弃了(不选这个点),那么可不可能选到两个相邻的点?由于相邻两点的边为无穷大,那么这条边肯定不会被割掉,也就是说要么和源点相连的点被割掉,要么和汇点相连的被割掉!这样建图,被割掉一定是和源点或汇点相连的边,切记。结果是权值总和减去最小割。

两点间建边无穷大,可以这么认为,目的是为了最大化取的点是相邻点的代价,通过这种方式使得相邻两点必定不能同时取(否则这个代价太大)。


2.方格内有固定权值,可以取相邻的数,如果相邻的数被取走,那么需要付出一个这两个数同时被取走的代价,问怎样取使得权值最大。

同样奇偶建图,源汇分别和自己掌管的点建边,容量为权值。现在重点来了,因为可以同时取走相邻的点,那么我们相邻点之间就不能建边无穷大来约束了。其实约束条件其实就是相邻两点被取走的代价。怎么理解?如果同时取走两点的代价超过取走这两点带来的价值,那么说明这个方案不是最优的,因为显然我们可以只取其中一点。第一类问题其实就是通过将约束条件无穷大化来约束使得不能同时选择相邻的两点而已。


3.方格内有两种属性的权值,每个方格可以取其中一个属性的权值,可以取相邻的数,如果取走的相邻方格属于同一属性,需要花费相应的代价,问怎样取使得权值最大。

建图稍微不同:奇属性的格子的第一种属性和源点建边,第二种属性和汇点建边,容量为该属性在该格子对应的权值。偶属性的格子的第一种属性和汇点建边,第二种属性和源点建边,容量为该属性在该格子对应的权值。这样由于同一个格子我们只能取走其中一个属性的权值,那么对这两个属性建边无穷大约束一下就好。相邻两点取走相同属性怎么办?其实只要对该点的和源点相连的属性对相邻点的同一属性建边就行了(相邻点和该点同一属性则相邻点的该属性必定和汇点相连),约束条件就是代价。这样建图以后,每个点要么选取其中一个属性,要么都不选。


总结一下这一类问题,基本是奇偶建图,然后如果要求能取相邻点,那么相邻点建边,容量为代价,否则建边无穷大约束。建边无穷大可以约束两个条件使至多只能选取一个。


本题属于第三种情况。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<iomanip>
#include<queue>
#include<cmath>
#include<stack>
#include<map>
#include<vector>
#include<set>
#include<algorithm>
using namespace std;
typedef long long LL;
const int int_max = 0x07777777;
const int int_min = 0x80000000;
const int maxn = 55*55*2;struct Edge{int from, to, cap, flow;Edge(int _from, int _to, int _cap, int _flow):from(_from),to(_to),cap(_cap),flow(_flow){}
};
vector<Edge> es;
vector<int> g[maxn];
int result,n,m,s,t,G,S;
int p[maxn],d[maxn],gap[maxn],cur[maxn],A[55][55],B[55][55];
void addedge (int from, int to, int cap){es.push_back(Edge(from, to, cap, 0));es.push_back(Edge(to, from, 0,0));int num = es.size();g[from].push_back(num-2);g[to].push_back(num-1);
}
void BFS (){queue<int> q;memset(d, 0, sizeof(d));d[t] = 0;q.push(t);while(!q.empty()){int u = q.front();q.pop();for(int i = 0; i < g[u].size(); i++){Edge& e = es[g[u][i]];if(e.cap==0 && d[e.to]==0){d[e.to] = d[u]+1;q.push(e.to);}}}
}
int augment (){int x = t;int a = int_max;while(x!=s){Edge& e = es[p[x]];a = (a < e.cap-e.flow ? a : e.cap-e.flow);x = es[p[x]].from;}x = t;while(x!=s){es[p[x]].flow += a;es[p[x]^1].flow -= a;x = es[p[x]].from;}return a;
}
int sap (){int flow = 0;BFS();memset(gap, 0, sizeof(gap));for(int i = 0; i <= t; i++) gap[d[i]]++;int x = s;memset(cur, 0, sizeof(cur));while(d[s] < t+1){if(x==t){flow += augment();x = s;}int ok = 0;for(int i = 0; i < g[x].size(); i++){Edge& e = es[g[x][i]];if(e.cap > e.flow && d[x]==d[e.to]+1){ok = 1;p[e.to] = g[x][i];cur[x] = i;x = e.to;break;}}if(!ok){int mm = t;for(int i = 0; i < g[x].size(); i++){Edge& e = es[g[x][i]];if(e.cap > e.flow) mm = (mm > d[e.to] ? d[e.to] : mm);}if(--gap[d[x]] == 0) break;gap[d[x]=mm+1]++;cur[x] = 0;if(x!=s) x = es[p[x]].from;}}return flow;
}int main(int argc, const char * argv[])
{int T;cin >> T;int count = 0;while(T--){scanf("%d %d %d %d", &n, &m, &G, &S);int total = 0;for(int i = 0; i < n; i++){for(int j = 0; j < m; j++) {scanf("%d", &A[i][j]);total += A[i][j];}}for(int i = 0; i < n; i++){for(int j = 0; j < m; j++) {scanf("%d", &B[i][j]);total += B[i][j];}}es.clear();s = n*m*2;t = s+1;int dir[4][2] = {-1,0,0,1,1,0,0,-1};for(int i = 0; i < maxn; i++) g[i].clear();for(int i = 0; i < n; i++){for(int j = 0; j < m; j++){if((i+j)%2==0){addedge(s, i*m+j, A[i][j]);addedge(i*m+j, i*m+j+n*m, int_max);addedge(i*m+j+n*m, t, B[i][j]);for(int u = 0; u < 4; u++){int ii = i + dir[u][0];int jj = j + dir[u][1];if(ii>=0 && ii<n && jj>=0 && jj<m){addedge(i*m+j, ii*m+jj, G);}}}else{addedge(s, i*m+j+n*m, B[i][j]);addedge(i*m+j+n*m, i*m+j, int_max);addedge(i*m+j, t, A[i][j]);for(int u = 0; u < 4; u++){int ii = i + dir[u][0];int jj = j + dir[u][1];if(ii>=0 && ii<n && jj>=0 && jj<m){addedge(i*m+j+n*m, ii*m+jj+n*m, S);}}}}}printf("Case %d: %d\n",++count,total-sap());}
}


这篇关于网络流 方格取数类型题的总结 + HDU3820的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/976395

相关文章

Python中logging模块用法示例总结

《Python中logging模块用法示例总结》在Python中logging模块是一个强大的日志记录工具,它允许用户将程序运行期间产生的日志信息输出到控制台或者写入到文件中,:本文主要介绍Pyt... 目录前言一. 基本使用1. 五种日志等级2.  设置报告等级3. 自定义格式4. C语言风格的格式化方法

Debian 13升级后网络转发等功能异常怎么办? 并非错误而是管理机制变更

《Debian13升级后网络转发等功能异常怎么办?并非错误而是管理机制变更》很多朋友反馈,更新到Debian13后网络转发等功能异常,这并非BUG而是Debian13Trixie调整... 日前 Debian 13 Trixie 发布后已经有众多网友升级到新版本,只不过升级后发现某些功能存在异常,例如网络转

Spring 依赖注入与循环依赖总结

《Spring依赖注入与循环依赖总结》这篇文章给大家介绍Spring依赖注入与循环依赖总结篇,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1. Spring 三级缓存解决循环依赖1. 创建UserService原始对象2. 将原始对象包装成工

Python中Json和其他类型相互转换的实现示例

《Python中Json和其他类型相互转换的实现示例》本文介绍了在Python中使用json模块实现json数据与dict、object之间的高效转换,包括loads(),load(),dumps()... 项目中经常会用到json格式转为object对象、dict字典格式等。在此做个记录,方便后续用到该方

python中的显式声明类型参数使用方式

《python中的显式声明类型参数使用方式》文章探讨了Python3.10+版本中类型注解的使用,指出FastAPI官方示例强调显式声明参数类型,通过|操作符替代Union/Optional,可提升代... 目录背景python函数显式声明的类型汇总基本类型集合类型Optional and Union(py

MySQL中查询和展示LONGBLOB类型数据的技巧总结

《MySQL中查询和展示LONGBLOB类型数据的技巧总结》在MySQL中LONGBLOB是一种二进制大对象(BLOB)数据类型,用于存储大量的二进制数据,:本文主要介绍MySQL中查询和展示LO... 目录前言1. 查询 LONGBLOB 数据的大小2. 查询并展示 LONGBLOB 数据2.1 转换为十

Python开发简易网络服务器的示例详解(新手入门)

《Python开发简易网络服务器的示例详解(新手入门)》网络服务器是互联网基础设施的核心组件,它本质上是一个持续运行的程序,负责监听特定端口,本文将使用Python开发一个简单的网络服务器,感兴趣的小... 目录网络服务器基础概念python内置服务器模块1. HTTP服务器模块2. Socket服务器模块

MyBatis的xml中字符串类型判空与非字符串类型判空处理方式(最新整理)

《MyBatis的xml中字符串类型判空与非字符串类型判空处理方式(最新整理)》本文给大家介绍MyBatis的xml中字符串类型判空与非字符串类型判空处理方式,本文给大家介绍的非常详细,对大家的学习或... 目录完整 Hutool 写法版本对比优化为什么status变成Long?为什么 price 没事?怎

Go语言网络故障诊断与调试技巧

《Go语言网络故障诊断与调试技巧》在分布式系统和微服务架构的浪潮中,网络编程成为系统性能和可靠性的核心支柱,从高并发的API服务到实时通信应用,网络的稳定性直接影响用户体验,本文面向熟悉Go基本语法和... 目录1. 引言2. Go 语言网络编程的优势与特色2.1 简洁高效的标准库2.2 强大的并发模型2.

C#之枚举类型与随机数详解

《C#之枚举类型与随机数详解》文章讲解了枚举类型的定义与使用方法,包括在main外部声明枚举,用于表示游戏状态和周几状态,枚举值默认从0开始递增,也可手动设置初始值以生成随机数... 目录枚举类型1.定义枚举类型(main外)2.使用生成随机数总结枚举类型1.定义枚举类型(main外)enum 类型名字