P2805 [NOI2009]植物大战僵尸 (拓扑排序 + 最小割)
题意: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]植物大战僵尸 (拓扑排序 + 最小割)的更多相关文章
- 【BZOJ-1565】植物大战僵尸 拓扑排序 + 最小割
1565: [NOI2009]植物大战僵尸 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1972 Solved: 917[Submit][Statu ...
- 【bzoj1565】[NOI2009]植物大战僵尸 拓扑排序+最大权闭合图
原文地址:http://www.cnblogs.com/GXZlegend/p/6808268.html 题目描述 输入 输出 仅包含一个整数,表示可以获得的最大能源收入.注意,你也可以选择不进行任何 ...
- 洛谷 P2805 [NOI2009]植物大战僵尸 解题报告
P2805 [NOI2009] 植物大战僵尸 题目描述 Plants vs. Zombies(PVZ)是最近十分风靡的一款小游戏.Plants(植物)和Zombies(僵尸)是游戏的主角,其中Plan ...
- P2805 [NOI2009]植物大战僵尸(最小割+拓扑排序)
题意: n*m的矩阵,每个位置都有一个植物.每个植物都有一个价值(可以为负),以及一些它可以攻击的位置.从每行的最右面开始放置僵尸,僵尸从右往左行动,当僵尸在植物攻击范围内时会立刻死亡.僵尸每到一个位 ...
- 洛谷2805 [NOI2009]植物大战僵尸 (拓扑排序+最小割)
坚决抵制长题面的题目! 首先观察到这个题目中,我们会发现,我们对于原图中的保护关系(一个点右边的点对于这个点也算是保护) 相当于一种依赖. 那么不难看出这个题实际上是一个最大权闭合子图模型. 我们直接 ...
- P2805 [NOI2009]植物大战僵尸 + 最大权闭合子图 X 拓扑排序
传送门:https://www.luogu.org/problemnew/show/P2805 题意 有一个n * m的地图,你可以操纵僵尸从地图的右边向左边走,走的一些地方是有能量值的,有些地方会被 ...
- BZOJ 1565 / P2805 [NOI2009]植物大战僵尸 (最大权闭合子图 最小割)
题意 自己看吧 BZOJ传送门 分析 - 这道题其实就是一些点,存在一些二元限制条件,即如果要选uuu则必须选vvv.求得到的权值最大是多少. 建一个图,如果选uuu必须选vvv,则uuu向vvv连边 ...
- 洛谷$P2805\ [NOI2009]$植物大战僵尸 网络流
正解:网络流 解题报告: 传送门$QwQ$ 题面好长昂,,,我大概概括下$QwQ$?有个$n\cdot m$的网格,每个格子有一株植物,击溃一株植物$(x,y)$需要付出$S_{(x,y)}$的代价( ...
- BZOJ 1565 植物大战僵尸(拓扑排序+最大权闭合子图)
图中的保护关系就类似于最大权闭合子图.即你想杀x,你就一定要杀掉保护x的点,那么把x向保护它的点连边.那么题目就转化成了最大权闭合子图的问题. 但是这个图有点特殊啊... 考虑有环的情况,显然这个环以 ...
随机推荐
- golang遍历时修改被遍历对象
目录 前言 遍历切片 遍历map 总结 前言 很多时候需要将遍历对象中去掉某些元素,或者往遍历对象中添加元素,这时候就需要小心操作了. 对于go语言中的一些注意事项我做了总结和示例,留下点笔记. 遍历 ...
- 在Linux系统下限制指定目录的大小以及文件/文件夹数量
背景说明 在Linux操作系统下有时需要限制一个指定文件夹的大小和文件夹内可存储的文件数量,有可能是出于安全的考量或者定制化的配置,这里我们提供了一种方案:用dd创建一个空的img镜像,进行格式化的配 ...
- 【Linux】saltstack的使用详解 超详细
一.salt常用命令 salt 该命令执行salt的执行模块,通常在master端运行,也是我们最常用到的命令 salt [options] '<target>' <function ...
- 优化太多的if-else
来源java小当家 第1种方法:提前return,减少else判断 1 // 1.优化前 2 private int handlerPre1(boolean flag) { 3 if(flag){ 4 ...
- watchdog应用实例
watchdog应用实例 By 鬼猫猫 20130504 http://www.cnblogs.com/muyr/ 实例:监测某文件夹,一旦文件夹里有文件,就把它剪切到其他服务器 import sys ...
- Seata RPC 模块的重构之路
简介: RPC 模块是我最初研究 Seata 源码开始的地方,因此我对 Seata 的 RPC 模块有过一些深刻研究,在我研究了一番后,发现 RPC 模块中的代码需要进行优化,使得代码更加优雅,交互逻 ...
- jQuery 当前展开其他收缩 三级下拉菜单(转载)
jQuery可展开收缩三级下拉菜单 <!DOCTYPE html> <html> <head> <meta charset="UTF-8" ...
- MySQL调优性能监控之performance schema
一.performance_schema的介绍 performance:性能 schema:图(表)示,以大纲或模型的形式表示计划或理论. MySQL的performance schema 用于监控M ...
- Linux下nf_conntrack(最全面)_董明磊-CSDN博客_nf_conntrack https://blog.csdn.net/qq_35299863/article/details/79530732
Linux下nf_conntrack(最全面)_董明磊-CSDN博客_nf_conntrack https://blog.csdn.net/qq_35299863/article/details/79 ...
- How Load Balancing Policies Work
How Load Balancing Policies Work https://docs.cloud.oracle.com/en-us/iaas/Content/Balance/Reference/ ...