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向保护它的点连边.那么题目就转化成了最大权闭合子图的问题. 但是这个图有点特殊啊... 考虑有环的情况,显然这个环以 ...
随机推荐
- RedHat6.1通过配置yum server安装软件包
1.获取镜像RHEL_6.1\ x86_64\ Disc\ 1 2.配置yum server #cd /etc/yum.repos.d #tar -cvf 20141114bak.tar *.repo ...
- 深入汇编指令理解Java关键字volatile
volatile是什么 volatile关键字是Java提供的一种轻量级同步机制.它能够保证可见性和有序性,但是不能保证原子性 可见性 对于volatile的可见性,先看看这段代码的执行 flag默认 ...
- linux服务开机自启动&注册系统服务
首先先看下linux系统开机启动顺序,如下图 对,要解决Linux CentOS 和 Red Hat Linux 系统中设置服务自启动有两种方式,就是从图中圈出的两个步骤下手. 一.修改 /etc/r ...
- Getshell
GetShell 常用免杀大法 一.编码大法 (1).一句话马子本身采用编码 原文:<?php @eval($_GET(a)):?> 转码后:在提交的post的时候可以直接使用\u0026 ...
- 痞子衡嵌入式:MCUBootFlasher v3.0发布,为真实的产线操作场景而生
-- 痞子衡维护的NXP-MCUBootFlasher工具(以前叫RT-Flash)距离上一个版本(v2.0.0)发布过去一年半以上了,这一次痞子衡为大家带来了全新版本v3.0.0,从这个版本开始,N ...
- salesforce零基础学习(一百)Mobile Device Tracking
本篇参考: Mobile Device Tracking (salesforce.com) UserDevice | SOAP API Developer Guide | Salesforce Dev ...
- Bitter.Core系列七:Bitter ORM NETCORE ORM 全网最粗暴简单易用高性能的 NETCore ORM 示例 更新删除插入
Bitter Orm 在操作数据库增删改的时候,支持模型驱动和直接执行裸SQL 操作,示例代码如下: 一:模型驱动(增删改) /// <summary> /// 插入,删除,更新示例(模型 ...
- etcd 与 Zookeeper、Consul 等其它 kv 组件的对比
基于etcd的分布式配置中心 etcd docs | etcd versus other key-value stores https://etcd.io/docs/v3.4.0/learning/w ...
- 逻辑bug 测试用例
1. 179. 最大数 - 力扣(LeetCode) https://leetcode-cn.com/problems/largest-number/ 给定一组非负整数 nums,重新排列它们每个数字 ...
- win api 窗口操作-窗口置顶与寻找与激活
https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowpos https://docs.micr ...