题目大意

​  给你一个\(n\times m\)的地图,每个格子上都有一颗植物,有的植物能保护其他植物。僵尸从右往左进攻,每吃掉一颗植物就可以得到\(a_{i,j}\)的收益(\(a_{i,j}\)可以是负数)。求僵尸的最大收益

​  \(1\leq n\leq20,1\leq m\leq30\)

题解

​  这种一个东西可以保护另一个东西而且数据范围那么小的题目显然是最大权闭合子图。

​  僵尸从右往左进攻,所以一棵植物可以保护它左边的植物。

​  如果保护关系形成一个环,就都不能选。

​  直接套模板即可。

​  可能需要一些优化

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
#include<queue>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
struct list
{
int v[1000010];
int w[1000010];
int t[1000010];
int h[1010];
int n;
list()
{
memset(h,0,sizeof h);
n=0;
}
void add(int x,int y,int z)
{
n++;
v[n]=y;
w[n]=z;
t[n]=h[x];
h[x]=n;
}
};
list l,l2;
void add(int x,int y,int z)
{
l.add(x,y,z);
l.add(y,x,0);
}
int n,m;
int w[110][110];
int gx[1010];
int gy[1010];
int id(int x,int y)
{
return (x-1)*m+y;
}
int vis[1010];
int b[1010];
void dfs(int x)
{
vis[x]=1;
int i;
for(i=l2.h[x];i;i=l2.t[i])
{
if(!vis[l2.v[i]])
dfs(l2.v[i]);
if(b[l2.v[i]]||vis[l2.v[i]]==1)
{
// w[gx[x]][gy[x]]=-10000000;
b[x]=1;
}
}
vis[x]=2;
}
int d[1010];
int S,T;
int c[30][40][30][40];
int bfs()
{
memset(d,-1,sizeof d);
queue<int> q;
q.push(S);
d[S]=0;
int x,i;
while(!q.empty())
{
x=q.front();
q.pop();
for(i=l.h[x];i;i=l.t[i])
if(l.w[i]&&d[l.v[i]]==-1)
{
d[l.v[i]]=d[x]+1;
if(l.v[i]==T)
return 1;
q.push(l.v[i]);
}
}
return 0;
}
int op(int x)
{
return ((x-1)^1)+1;
}
int dfs(int x,int flow)
{
if(x==T)
return flow;
int c,s=0,i;
for(i=l.h[x];i;i=l.t[i])
if(l.w[i]&&d[l.v[i]]==d[x]+1)
{
c=dfs(l.v[i],min(flow,l.w[i]));
s+=c;
flow-=c;
l.w[i]-=c;
l.w[op(i)]+=c;
if(!flow)
break;
}
if(flow)
d[x]=-1;
return s;
}
int main()
{
memset(b,0,sizeof b);
memset(c,0,sizeof c);
// freopen("bzoj1565.in","r",stdin);
// freopen("bzoj1565.out","w",stdout);
scanf("%d%d",&n,&m);
S=n*m+1;
T=S+1;
int sum=0;
int i,j,k,o,x,y,u;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
scanf("%d",&w[i][j]);
gx[id(i,j)]=i;
gy[id(i,j)]=j;
scanf("%d",&u);
for(k=1;k<=u;k++)
{
scanf("%d%d",&x,&y);
x++;
y++;
c[i][j][x][y]=1;
}
if(j>1)
c[i][j][i][j-1]=1;
for(x=1;x<=n;x++)
for(y=1;y<=m;y++)
if(c[i][j][x][y])
l2.add(id(x,y),id(i,j),0);
}
memset(vis,0,sizeof vis);
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
if(!vis[id(i,j)])
dfs(id(i,j));
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
if(!b[id(i,j)])
{
if(w[i][j]>0)
{
sum+=w[i][j];
add(S,id(i,j),w[i][j]);
}
else
add(id(i,j),T,-w[i][j]);
for(x=1;x<=n;x++)
for(y=1;y<=m;y++)
if(c[i][j][x][y])
if(!b[id(x,y)])
add(id(x,y),id(i,j),0x7fffffff);
}
int ans=0;
while(bfs())
ans+=dfs(S,0x7fffffff);
printf("%d\n",sum-ans);
return 0;
}

【BZOJ1565】【NOI2009】植物大战僵尸 网络流 最大权闭合子图的更多相关文章

  1. BZOJ1565 [NOI2009]植物大战僵尸 【最大权闭合子图 + tarjan缩点(或拓扑)】

    题目 输入格式 输出格式 仅包含一个整数,表示可以获得的最大能源收入.注意,你也可以选择不进行任何攻击,这样能源收入为0. 输入样例 3 2 10 0 20 0 -10 0 -5 1 0 0 100 ...

  2. [BZOJ1565][NOI2009]植物大战僵尸-[网络流-最小割+最大点权闭合子图+拓扑排序]

    Description 传送门 Solution em本题知识点是用网络流求最大点权闭合子图. 闭合图定义:图中任何一个点u,若有边u->v,则v必定也在图中. 建图:运用最小割思想,将S向点权 ...

  3. bzoj1565: [NOI2009]植物大战僵尸 最大权闭合子图,tarjan

    bzoj1565: [NOI2009]植物大战僵尸 链接 https://www.lydsy.com/JudgeOnline/problem.php?id=1565 思路 很容易的想到最大权闭合子图 ...

  4. BZOJ1565 [NOI2009]植物大战僵尸(拓扑排序 + 最大权闭合子图)

    题目 Source http://www.lydsy.com/JudgeOnline/problem.php?id=1565 Description Input Output 仅包含一个整数,表示可以 ...

  5. BZOJ1565[NOI2009]植物大战僵尸——最大权闭合子图+拓扑排序

    题目描述 Plants vs. Zombies(PVZ)是最近十分风靡的一款小游戏.Plants(植物)和Zombies(僵尸)是游戏的主角,其中Plants防守,而Zombies进攻.该款游戏包含多 ...

  6. [bzoj1565][NOI2009]植物大战僵尸_网络流_拓扑排序

    植物大战僵尸 bzoj1565 题目大意:给你一张网格图,上面种着一些植物.你从网格的最右侧开始进攻.每个植物可以对僵尸提供能量或者消耗僵尸的能量.每个植物可以保护一个特定网格内的植物,如果一个植物被 ...

  7. BZOJ 1565 [NOI2009]植物大战僵尸 | 网络流

    传送门 BZOJ 1565 题解 这道题也是个经典的最大权闭合子图-- 复习一下最大权闭合子图是什么? 就是一个DAG上,每个点有个或正或负的点权,有的点依赖于另外一些点(如果选这个点,则被依赖点必选 ...

  8. 洛谷$P2805\ [NOI2009]$植物大战僵尸 网络流

    正解:网络流 解题报告: 传送门$QwQ$ 题面好长昂,,,我大概概括下$QwQ$?有个$n\cdot m$的网格,每个格子有一株植物,击溃一株植物$(x,y)$需要付出$S_{(x,y)}$的代价( ...

  9. BZOJ 1565 植物大战僵尸(最大权闭合图)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1565 题意:植物大战僵尸,一个n*m的格子,每 个格子里有一个植物,每个植物有两个属性: ...

随机推荐

  1. JS 原型与原型链

    图解: 一.普通对象 跟 函数对象 JavaScript 中,一切皆对象.但对象也有区别,分为 普通对象 跟 函数对象,Object 和 Function 是 JavaScript 自带的函数对象. ...

  2. hdu5943素数间隙与二分匹配

    题意: 给出n和s,匹配(s+1,s+2,s+3......s+n)和(1,2,3,4,5........n)让(s+x)%x==0,判断是否有解 思路: 先用程序跑一边,发现1到1e9得素数间隙小于 ...

  3. NFV论文集(二)

    一 文章名称:VNF Placement with Replication for Load Balancing in NFV Networks 发表时间:2017 期刊来源:ICC: IEEE In ...

  4. PS 十分钟教你做出文字穿插效果

  5. python知识点及面试面试大集合

    题目来源:武sir--一个很有意思的人,点击这儿跳转 一.基础篇 为什么学习Python? 通过什么途径学习的Python? Python和Java.PHP.C.C#.C++等其他语言的对比? 简述解 ...

  6. java web石家庄铁道大学课程管理系统

    package kecheng Kc.java package kecheng; public class Kc { private int id; private String classname; ...

  7. 关于JS动画和CSS3动画的性能差异

    本文章为综合其它资料所得. 根据Google Developer,Chromium项目里,渲染线程分为main thread和compositor thread. 如果CSS动画只是改变transfo ...

  8. Jquery 选择器 特殊字符 转义字符

    1.Jquery   选择器 id包含特殊字符,加双斜线 \\ 例 <input type="text" id="dbo_HouseInfo.HouseResour ...

  9. Oracle Flashback 详解

    Oracle flashback 是一种方便快捷的数据库恢复技术,它不使用备份文件,通过闪回日志可以使数据库恢复到过去的某个状态,当用户发生逻辑错误时(误删表数据.表.表空间等)需要快速恢复数据库,可 ...

  10. cmd远程连接oracle数据库