题意: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. 浅谈localStorage的使用场景和优劣势,以及sessionStorage和cookie

    一.localStorage,sessionStorage,cookie的简单介绍 localStorage:仅在客户端存储不参与服务器通信,存储大小一般为5M,如果不是人为清除,那么即使是关闭浏览器 ...

  2. MySQL多版本并发控制——MVCC机制分析

    MVCC,即多版本并发控制(Multi-Version Concurrency Control)指的是,通过版本链维护一个数据的多个版本,使得读写操作没有冲突,可保证不同事务读写.写读操作并发执行,提 ...

  3. wpf 通过为DataGrid所绑定的数据源类型的属性设置Attribute改变DataGrid自动生成列的顺序

    环境Win10 VS2019 .Net Framework4.8 在wpf中,如果为一个DataGrid绑定到一个数据源,默认情况下DataGrid会为数据源类型的每个属性生成一个列(Column)对 ...

  4. xtrabackup 备份与恢复

    书上摘抄 ---深入浅出mysql 448页  grant reload on *.* to 'backup'@'localhost' identified by '123456'; grant re ...

  5. C#中foreach的实现原理

    C#中foreach的实现原理 在探讨foreach如何内部如何实现这个问题之前,我们需要理解两个C#里边的接口,IEnumerable 与 IEnumerator. 在C#里边的遍历集合时用到的相关 ...

  6. bash5.0参考手册

    Bash Reference Manual a.summary-letter { text-decoration: none } blockquote.indentedblock { margin-r ...

  7. service代理模式及负载均衡

    [root@k8s-master ~]# vim service.yaml apiVersion: v1 kind: Service metadata: name: my-service spec: ...

  8. postgresql中权限介绍

    postgresql权限分为实例的权限,数据库的权限,模式的权限,对象的权限,表空间的权限 实例的权限:由pg_hba.conf文件控制,控制那些用户那些IP以哪种方式连接数据库 数据库的权限:是否允 ...

  9. 为什么[] == false 为true

    首先要讲一下js的数据类型分为: 1.基本数据类型(原始数据类型):String.Boolean.Number.null.undefined.Symbol 2.引用数据类型:Object.Array. ...

  10. b站视频_下载_去水印_视频转mp4-批量下载神器

    b站下载_视频_去水印_转mp4_批量下载的解决办法 以下问题均可解决 b站下载的视频如何保存到本地 b站下载的视频在那个文件夹里 b站下载视频转mp4 b站下载app b站下载在哪 b站下载视频电脑 ...