BZOJ 1565 植物大战僵尸 最大权闭合子图+网络流
题意:
植物大战僵尸,一个n*m的格子,每 个格子里有一个植物,每个植物有两个属性:
(1)价值;
(2)保护集合,也就是这个植物可以保护矩阵中的某些格子。
现在你是僵尸,你每次只能从(i,m) 格子进入,从右向左进攻。若一个格子是被保护的那么你是不能进入的。每进入一个格子则吃掉该格子的植物并得到其价值(价值有可能是负的),可以中途返回。问可以得到的最大价值是多少?
分析:
这是一道比较真实的题目。(真打游戏的时候应该也是这种景象吧)
首先我们复习一下最大权闭合子图的特质。
有一个有向图,每一个点都有一个权值(可以为正或负或0),选择一个权值和最大的子图,使得每个点的后继都在子图里面,这个子图就叫最大权闭合子图。
上面这句话我们要提炼出一个极其重要的信息:如果我们选择一个点,那就必须选择它的所有后继。
凡是题目中隐含着这样的条件的,我们都可以往最大权闭合子图方向去想一想。
像这道题,每个植物可以保护一些其他的植物。那就意味着,如果我们想要选择一个植物,我们必须首先把所有保护它的植物都选掉。
这样,我们就可以建图,对于一个点x,假如有点y可以保护点x,那么我们就连一条x—>y的边,注意,边的方向和保护的方向是相反的。
(这里有好多题解都不是这么说的,或许另有高论?)
还隐含着一个条件:右边的始终植物保护着左边的植物(对吧?植物大战僵尸里是这样的吧,所以诞生了高坚果)
我们建图,跑最大权闭合子图就好了吗?
并不是……
因为环是无敌的……???!!!
如果在保护关系中出现了环,那么你选任何一个,都是被保护的。
所以我们拓扑,把环的影响取消掉,再跑最大权闭合子图的恶意……
从源点s向每个正权点连一条容量为权值的边,每个负权点向汇点t连一条容量为权值的绝对值的边,有向图原来的边容量全部为无限大答案为正权值之和-最小割
代码:
#include<bits/stdc++.h>
#define ms(a,x) memset(a,x,sizeof(a))
using namespace std;int tot=,n,m,sm=;
const int N=,inf=0x3f3f3f3f;
struct node{int y,z,nxt;}e[N*];
int h[N],c=,q[N],in[N],S,T,d[N],a[N],ans=;
void add(int x,int y,int z){in[x]++;
e[++c]=(node){y,z,h[x]};h[x]=c;
e[++c]=(node){x,,h[y]};h[y]=c;
} bool bfs(){
for(int i=S;i<=T;i++)
if(d[i]!=-) d[i]=-;
int f=,t=;d[S]=;q[++t]=S;
while(f<=t){
int x=q[f++];
for(int i=h[x],y;i;i=e[i].nxt)
if(d[y=e[i].y]==-&&e[i].z)
d[y]=d[x]+,q[++t]=y;
} return (d[T]>);
} int dfs(int x,int f){
if(x==T) return f;int w,tmp=;
for(int i=h[x],y;i;i=e[i].nxt)
if(d[y=e[i].y]==d[x]+&&e[i].z){
w=dfs(y,min(e[i].z,f-tmp));
if(!w) d[y]=-;e[i].z-=w;
e[i^].z+=w;tmp+=w;
if(tmp==f) return f;
} return tmp;
} void solve(){
while(bfs()) tot+=dfs(S,inf);
} int main(){
scanf("%d%d",&n,&m);S=;T=n*m+;
for(int i=,tmp;i<=n*m;i++){
scanf("%d",&a[i]);
a[i]>?add(S,i,a[i]):add(i,T,-a[i]);
scanf("%d",&tmp);while(tmp--){
int x,y;scanf("%d%d",&x,&y);
add(x*m+y+,i,inf);
} if(i%m) add(i,i+,inf);
} int f=,t=;//图是反着建的,拓扑要倒过来
for(int i=S;i<=T;d[i]=-,i++)
if(!in[i]) q[++t]=i;
while(f<=t){
int x=q[f++];d[x]=;
if(a[x]>) sm+=a[x];
for(int i=h[x];i;i=e[i].nxt)
if(i&)if(!--in[e[i].y]) q[++t]=e[i].y;
} solve();
printf("%d\n",sm-tot);return ;
}
最大权闭合子图
BZOJ 1565 植物大战僵尸 最大权闭合子图+网络流的更多相关文章
- BZOJ 1565 / P2805 [NOI2009]植物大战僵尸 (最大权闭合子图 最小割)
题意 自己看吧 BZOJ传送门 分析 - 这道题其实就是一些点,存在一些二元限制条件,即如果要选uuu则必须选vvv.求得到的权值最大是多少. 建一个图,如果选uuu必须选vvv,则uuu向vvv连边 ...
- bzoj1565: [NOI2009]植物大战僵尸 最大权闭合子图,tarjan
bzoj1565: [NOI2009]植物大战僵尸 链接 https://www.lydsy.com/JudgeOnline/problem.php?id=1565 思路 很容易的想到最大权闭合子图 ...
- BZOJ1565[NOI2009]植物大战僵尸——最大权闭合子图+拓扑排序
题目描述 Plants vs. Zombies(PVZ)是最近十分风靡的一款小游戏.Plants(植物)和Zombies(僵尸)是游戏的主角,其中Plants防守,而Zombies进攻.该款游戏包含多 ...
- P2805 [NOI2009]植物大战僵尸 + 最大权闭合子图 X 拓扑排序
传送门:https://www.luogu.org/problemnew/show/P2805 题意 有一个n * m的地图,你可以操纵僵尸从地图的右边向左边走,走的一些地方是有能量值的,有些地方会被 ...
- BZOJ 1565 植物大战僵尸(拓扑排序+最大权闭合子图)
图中的保护关系就类似于最大权闭合子图.即你想杀x,你就一定要杀掉保护x的点,那么把x向保护它的点连边.那么题目就转化成了最大权闭合子图的问题. 但是这个图有点特殊啊... 考虑有环的情况,显然这个环以 ...
- BZOJ 1565 植物大战僵尸(最大权闭合图)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1565 题意:植物大战僵尸,一个n*m的格子,每 个格子里有一个植物,每个植物有两个属性: ...
- codeforces 1082G - Petya and Graph 最大权闭合子图 网络流
题意: 让你选一些边,选边的前提是端点都被选了,求所有的边集中,边权和-点权和最大的一个. 题解: 对于每个边建一个点,然后就是裸的最大权闭合子图, 结果比赛的时候我的板子太丑,一直T,(不会当前弧优 ...
- hiho# 1398 最大权闭合子图 网络流
题目传送门 题意:给出n个活动,m个人,请人需要花费$a[i]$的钱,举办一次活动可以赚$b[i]$的钱,但是需要固定的几个人在场,一个人只需要请一次后就必定在场,问最大收益. 思路: 下列结论来自h ...
- Bzoj 1565: [NOI2009]植物大战僵尸 最大权闭合图,拓扑排序
题目: http://cojs.tk/cogs/problem/problem.php?pid=410 410. [NOI2009] 植物大战僵尸 ★★★ 输入文件:pvz.in 输出文件:p ...
随机推荐
- JS 对java返回的json格式的数据处理
var dataObj=eval("("+res+")"); alert(dataObj.billBuy) //res是如下的数据 {"billBuy ...
- get与post提交方式区别?
1.get <!--表单数据作为HTTP GET请求发送给action 规定的URL,并将数据附加在URL之后,由客户端直接发送给服务器.表单数据不能太长,也不能含有非ASCII码的字符--&g ...
- jQuery入坑指南
前言 Ajax官方文档 爱jQuery jQuery插件库 jQuery中文api input 赋值和取值 记录一下: 在写一个input赋值,二话不说就直接利用了$('#xx').val()来进行取 ...
- mybatis基础学习5---懒加载和缓存
1:懒加载 1)在主配置文件设置(要放在配置文件最前面) 1 <!-- 延迟加载配置,两个都必须同时有 --> <settings> 3 <!-- lazyLoading ...
- Linux 常用命令十二 top
一.top命令 top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器. top显示系统当前的进程和其他状况,是一个动态显示过程,即可以 ...
- NOIp 2010/Luogu P1525 关押罪犯 【二分图/并查集】 By cellur925
题目传送门 感想:相信自己的想法!继续挖掘! 读完题目后:看到的最大值最小?二分答案啊!再仔细一看:wi达到了1e9,二分可能费点劲.(其实真的是可以的)而且check函数貌似并没有什么行之有效的写法 ...
- 【洛谷3822】[NOI2017] 整数(线段树压位)
题目: 洛谷 3822 分析: 直接按题意模拟,完了. 将每次加 / 减拆成不超过 \(32\) 个对单独一位的加 / 减. 考虑给一个二进制位(下称「当前位」)加 \(1\) 时,如果这一位本来就是 ...
- bryce1010专题训练——线段树习题汇总
一.区间查询,无单点更新 hdu2795 Billboard Time Limit: 20000/8000 MS (Java/Others) Memory Limit: 32768/32768 ...
- 逆序数 UVALive 6508 Permutation Graphs
题目传送门 /* 题意:给了两行的数字,相同的数字连线,问中间交点的个数 逆序数:第一行保存每个数字的位置,第二行保存该数字在第一行的位置,接下来就是对它求逆序数 用归并排序或线段树求.想到了就简单了 ...
- 2016/10/29 Action类中execute方法的使用
第一步:先配置web.xml文件 <filter> <filter-name>struts2</filter-name> <filter-class>o ...