题目大意

​  给你一个\(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. python第六章:三大利器(装饰器,迭代器,生成器)--小白博客

    python装饰器 什么是装饰器?在不修改源代码和调用方式的基础上给其增加新的功能,多个装饰器可以装饰在同一个函数上 # 原理(个人理解):将原函数(bar)的内存地址重新赋值,进行覆盖.新值为装饰器 ...

  2. Leetcode 686 Repeated String Match

    Given two strings A and B, find the minimum number of times A has to be repeated such that B is a su ...

  3. 一些leetcode算法题

    DFS算法 思想:一直往深处走,直到找到解或者走不下去为止 DFS(dep,...) // dep代表目前DFS的深度 { if (找到解或者走不下去了){ return; } 枚举下种情况,DFS( ...

  4. java 接口实现防盗门功能

    Door: package locker; public abstract class Door { public abstract void open(); public abstract void ...

  5. struts2之配置文件struts.xml详解

    struts配置文件 struts.xml配置参数详解 struts.xml中很大一部分配置默认配置就好了 但是有些还是需要做了解  以便于理解 和修改 <?xml version=" ...

  6. pycharm 中 import requests 报错

    一 , 使用Pycharm来抓取网页的时候,要导入requests模块,但是在pycharm中 import requests 报错. 原因: python中还没有安装requests库 解决办法: ...

  7. #Leetcode# 633. Sum of Square Numbers

    https://leetcode.com/problems/sum-of-square-numbers/ Given a non-negative integer c, your task is to ...

  8. [转帖]Windows 10新预览版上线:可直接运行任意安卓APP了

    Windows 10新预览版上线:可直接运行任意安卓APP了 http://www.pcbeta.com/viewnews-80316-1.html 今晨(3月13日),微软面向Fast Ring(快 ...

  9. [转帖]分布式Unique ID的生成方法一览

    分布式Unique ID的生成方法一览 http://www.importnew.com/22211.html 分布式的Unique ID的用途如此广泛,从业务对象Id到日志的TraceId,本文总结 ...

  10. 校园电商项目4——SSM各项配置

    步骤一:数据库连接文件 jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/school_o2o?useUni ...