题意:N*M的矩阵 每个点上都有一颗植物 僵尸只能从每一行的最右边向左进攻

   每个植物有攻击范围 可以保护在攻击范围内的植物 同时每一颗植物也保护他左边的植物

   摧毁每个植物能获得价值 如果这个植物被保护着就无法摧毁 求最大收益

题解:看了题解说 一个物品被若干物品保护着 要摧毁它必须先摧毁保护它的东西这种模型

   反向建边就是有向图中的闭合子图这个模型 求闭合子图的最大权十分套路

   把所有正权和源点连容量为权值大小的边 把负权点和汇点连容量为权值的绝对值大小的边

   权值等于0的点连谁都不影响 然后不同点之间有边就连容量为INF的边

   在这个图中跑一遍最小割 然后用正权点权值和 - 最小割就是 闭合子图的最大权了

   但是这个题有一个坑点 如果两个点互相保护 那么这两个点显然就都摧毁不了 所以我们要预先处理成环的点

   先正向连边 然后拓扑排序搞一搞就好了

#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f; int n, m, cnt, s, t, maxflow, ans;
struct node {
int to, nex, val;
}E[2000005];
int head[1005];
vector<int> g[1005];
int du[1005], vis[1005], val[1005]; void addedge(int x, int y, int va) {
E[++cnt].to = y; E[cnt].nex = head[x]; head[x] = cnt; E[cnt].val = va;
E[++cnt].to = x; E[cnt].nex = head[y]; head[y] = cnt; E[cnt].val = 0;
} int get(int x, int y) {return (x - 1) * m + y;} void topsort() {
queue<int> que;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
if(!du[get(i, j)]) que.push(get(i, j)), vis[get(i, j)] = 1; while(!que.empty()) {
int u = que.front();
que.pop();
for(int i = 0; i < g[u].size(); i++) {
int v = g[u][i];
du[v]--;
if(!du[v]) que.push(v), vis[v] = 1;
}
}
} int dis[1005], inque[1005], cur[1005];
bool bfs() {
for(int i = 1; i <= t; i++) dis[i] = INF, inque[i] = 0, cur[i] = head[i];
queue<int> que; que.push(s);
dis[s] = 0; inque[s] = 1; while(!que.empty()) {
int u = que.front();
que.pop();
inque[u] = 0;
for(int i = head[u]; i; i = E[i].nex) {
int v = E[i].to;
if(E[i].val && dis[v] == INF) {
dis[v] = dis[u] + 1;
if(!inque[v]) {
que.push(v);
inque[v] = 1;
}
}
}
}
return dis[t] != INF;
} int viss;
int dfs(int x, int flow) {
if(x == t) {
viss = 1;
maxflow += flow;
return flow;
} int used = 0, rflow = 0;
for(int i = cur[x]; i; i = E[i].nex) {
cur[x] = i;
int v = E[i].to;
if(E[i].val && dis[v] == dis[x] + 1) {
if(rflow = dfs(v, min(flow - used, E[i].val))) {
used += rflow;
E[i].val -= rflow;
E[i ^ 1].val += rflow;
if(used == flow) break;
}
}
}
if(!used) dis[x] = INF;
return used;
} void dinic() {
maxflow = 0;
while(bfs()) {
viss = 1;
while(viss) {
viss = 0;
dfs(s, INF);
}
}
} int main() {
ans = 0;
cnt = 1;
scanf("%d%d", &n, &m);
s = n * m + 1; t = s + 1;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++) {
int pos = get(i, j);
scanf("%d", &val[pos]); int w; scanf("%d", &w);
for(int i = 1; i <= w; i++) {
int x, y;
scanf("%d%d", &x, &y);
x++, y++;
int pos1 = get(x, y);
du[pos1]++; g[pos].push_back(pos1);
}
if(j != m) {
int pos2 = pos + 1;
du[pos]++; g[pos2].push_back(pos);
}
}
topsort(); for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++) {
int pos = get(i, j);
if(!vis[pos]) continue;
if(val[pos] >= 0) addedge(s, pos, val[pos]), ans += val[pos];
else addedge(pos, t, -val[pos]); for(int k = 0; k < g[pos].size(); k++) {
int v = g[pos][k];
if(vis[v]) addedge(v, pos, INF);
}
}
dinic();
//for(int i = 1; i <= n * m; i++) cout << vis[i] << endl;
//cout << ans << " " << maxflow << endl;
printf("%d\n", ans - maxflow);
return 0;
}

P2805 [NOI2009]植物大战僵尸 (拓扑排序 + 最小割)的更多相关文章

  1. 【BZOJ-1565】植物大战僵尸 拓扑排序 + 最小割

    1565: [NOI2009]植物大战僵尸 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1972  Solved: 917[Submit][Statu ...

  2. 【bzoj1565】[NOI2009]植物大战僵尸 拓扑排序+最大权闭合图

    原文地址:http://www.cnblogs.com/GXZlegend/p/6808268.html 题目描述 输入 输出 仅包含一个整数,表示可以获得的最大能源收入.注意,你也可以选择不进行任何 ...

  3. 洛谷 P2805 [NOI2009]植物大战僵尸 解题报告

    P2805 [NOI2009] 植物大战僵尸 题目描述 Plants vs. Zombies(PVZ)是最近十分风靡的一款小游戏.Plants(植物)和Zombies(僵尸)是游戏的主角,其中Plan ...

  4. P2805 [NOI2009]植物大战僵尸(最小割+拓扑排序)

    题意: n*m的矩阵,每个位置都有一个植物.每个植物都有一个价值(可以为负),以及一些它可以攻击的位置.从每行的最右面开始放置僵尸,僵尸从右往左行动,当僵尸在植物攻击范围内时会立刻死亡.僵尸每到一个位 ...

  5. 洛谷2805 [NOI2009]植物大战僵尸 (拓扑排序+最小割)

    坚决抵制长题面的题目! 首先观察到这个题目中,我们会发现,我们对于原图中的保护关系(一个点右边的点对于这个点也算是保护) 相当于一种依赖. 那么不难看出这个题实际上是一个最大权闭合子图模型. 我们直接 ...

  6. P2805 [NOI2009]植物大战僵尸 + 最大权闭合子图 X 拓扑排序

    传送门:https://www.luogu.org/problemnew/show/P2805 题意 有一个n * m的地图,你可以操纵僵尸从地图的右边向左边走,走的一些地方是有能量值的,有些地方会被 ...

  7. BZOJ 1565 / P2805 [NOI2009]植物大战僵尸 (最大权闭合子图 最小割)

    题意 自己看吧 BZOJ传送门 分析 - 这道题其实就是一些点,存在一些二元限制条件,即如果要选uuu则必须选vvv.求得到的权值最大是多少. 建一个图,如果选uuu必须选vvv,则uuu向vvv连边 ...

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

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

  9. BZOJ 1565 植物大战僵尸(拓扑排序+最大权闭合子图)

    图中的保护关系就类似于最大权闭合子图.即你想杀x,你就一定要杀掉保护x的点,那么把x向保护它的点连边.那么题目就转化成了最大权闭合子图的问题. 但是这个图有点特殊啊... 考虑有环的情况,显然这个环以 ...

随机推荐

  1. 基于Jmeter实现Rocketmq消息发送

    在互联网企业技术架构中,MQ占据了越来越重要的地位.系统解耦.异步通信.削峰填谷.数据顺序保证等场景中,到处都能看到MQ的身影. 而测试工程师在工作中,也经常需要和mq打交道,比如构造测试数据,触发某 ...

  2. HarmonyOS三方件开发指南(4)——Logger组件

    目录: 1.      Logger功能介绍 2.      Logger使用方法 3.      Logger开发实现 4.      源码上传地址 1.      Logger功能介绍1.1.   ...

  3. Array.apply(null, {length: 2}) 的理解

    // apply 的第二参数通常是数组 但是也可以传递类数组对象{length: 2}console.log(Array.apply(null, {length: 2})) // [undefined ...

  4. mac安装Navicat Premium Mac 12 破解版

    参考:https://www.cnblogs.com/lyfstorm/p/11123159.html 激活后:

  5. 深入剖析setState同步异步机制

    关于 setState setState 的更新是同步还是异步,一直是人们津津乐道的话题.不过,实际上如果我们需要用到更新后的状态值,并不需要强依赖其同步/异步更新机制.在类组件中,我们可以通过thi ...

  6. RandomForest 随机森林算法与模型参数的调优

    公号:码农充电站pro 主页:https://codeshellme.github.io 本篇文章来介绍随机森林(RandomForest)算法. 1,集成算法之 bagging 算法 在前边的文章& ...

  7. Linux Shell 编程基础详解——吐血整理,墙裂推荐!

    第一部分:Linux Shell 简介 Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁.Shell 既是一种命令语言,又是一种程序设计语言. Shell 是指一种应用程序, ...

  8. 07--Docker安装Redis

    1.拉取redis:3.2 docker pull redis:3.2 2.创建redis容器 docker run -p 6379:6379 -v /zhengcj/myredis/data:/da ...

  9. LuoguP5748 集合划分计数

    题意 一个有\(n\)个元素的集合,将其分为任意个非空子集,求方案数.集合之间是无序的,\(\{\{1,2\},\{3\}\}=\{\{3\},\{1,2\}\}\). 设\(f_n\)表示用\(n\ ...

  10. 记一次ceph pg unfound处理过程

    今天检查ceph集群,发现有pg丢失,于是就有了本文~~~ 1.查看集群状态 [root@k8snode001 ~]# ceph health detail HEALTH_ERR 1/973013 o ...