【BZOJ1565】【NOI2009】植物大战僵尸
好久没写博客了
题目
思路&做法
没什么好说的
应该很容易看出是 最大闭合子图 吧?
不过要注意一下的是,这题 可能有植物是不可能被击溃的 , 所以要先跑一遍 拓扑排序 把这些点排除掉
代码
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
const int N = 810, M = 500010;
const int INF = 0x7F7F7F7F;
int n, m;
int val[40][40];
vector< pair<int, int> > vec[40][40];
bool vis[N]; //vis为0的点就是不可能击溃的点
struct edge
{ int from, to, flow, cap;
edge() { }
edge(int _1, int _2, int _3, int _4) : from(_1), to(_2), flow(_3), cap(_4) { }
};
struct Dinic
{ edge edges[M];
int head[N], nxt[M], tot;
int L, R;
inline void init()
{ memset(head, -1, sizeof(head));
tot = 0;
}
void add_edge(int x, int y, int z)
{ edges[tot] = edge(x, y, 0, z);
nxt[tot] = head[x];
head[x] = tot++;
edges[tot] = edge(y, x, 0, 0);
nxt[tot] = head[y];
head[y] = tot++;
}
int s, t;
int d[N];
bool bfs()
{ memset(d, -1, sizeof(d));
queue<int> q;
q.push(s);
d[s] = 0;
while (!q.empty())
{ int x = q.front(); q.pop();
for (int i = head[x]; ~i; i = nxt[i])
{ edge & e = edges[i];
if (vis[e.to] && e.cap > e.flow && d[e.to] == -1)
{ d[e.to] = d[x] + 1;
q.push(e.to);
}
}
}
return d[t] != -1;
}
int cur[N];
int dfs(int x, int a)
{ if (x == t || a == 0) return a;
int flow = 0, f;
for (int & i = cur[x]; ~i; i = nxt[i])
{ edge & e = edges[i];
if (vis[e.to] && d[e.to] == d[x] + 1 && (f = dfs(e.to, min(a, e.cap-e.flow))) > 0)
{ e.flow += f;
edges[i^1].flow -= f;
a -= f;
flow += f;
if (!a) break;
}
}
return flow;
}
int maxflow(int _s, int _t)
{ s = _s, t = _t;
int flow = 0;
while (bfs())
{ for (int i = L; i <= R; i++)
cur[i] = head[i];
flow += dfs(s, INF);
}
return flow;
}
} dinic;
int S, T;
int in[N];
int num[N];
inline int id(int x, int y) { return (x-1)*m + y; }
void topo()
{ queue<int> q;
for (int i = 1; i <= n*m; i++)
if (!in[i]) q.push(i);
while (!q.empty())
{ int x = q.front(); q.pop();
vis[x] = 1;
for (int i = dinic.head[x]; ~i; i = dinic.nxt[i])
{ edge & e = dinic.edges[i];
if (e.to == S || e.to == T || in[e.to] == 0 || e.cap > e.flow)
continue;
if ((--in[e.to]) == 0)
q.push(e.to);
}
}
}
void build()
{ S = n * m + 1, T = n * m + 2;
dinic.init();
dinic.L = 0, dinic.R = n * m + 2;
for (int i = 1; i <= n; i++)
{ for (int j = 1; j <= m; j++)
{ if (val[i][j] > 0)
dinic.add_edge(S, id(i, j), val[i][j]);
if (val[i][j] < 0)
dinic.add_edge(id(i, j), T, -val[i][j]);
for (int k = 0; k < vec[i][j].size(); k++)
{ dinic.add_edge(id(vec[i][j][k].first, vec[i][j][k].second), id(i, j), INF);
in[id(vec[i][j][k].first, vec[i][j][k].second)]++;
}
if (j > 1)
dinic.add_edge(id(i, j-1), id(i, j), INF),
in[id(i, j-1)]++;
}
}
}
int main()
{ scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
{ int l;
scanf("%d %d", &val[i][j], &l);
num[id(i, j)] = val[i][j];
for (int k = 1; k <= l; k++)
{ int x, y;
scanf("%d %d", &x, &y);
x++, y++;
vec[i][j].push_back(make_pair(x, y));
}
}
build();
topo();
int ans = 0;
for (int i = 1; i <= n*m; i++)
if (vis[i] && num[i] > 0)
ans += num[i];
vis[S] = vis[T] = 1;
ans -= dinic.maxflow(S, T);
printf("%d\n", ans);
return 0;
}
【BZOJ1565】【NOI2009】植物大战僵尸的更多相关文章
- 【最大权闭合子图 tarjan】bzoj1565: [NOI2009]植物大战僵尸
dinic+tarjan板子练手题 Description Plants vs. Zombies(PVZ)是最近十分风靡的一款小游戏.Plants(植物)和Zombies(僵尸)是游戏的主角,其 中P ...
- BZOJ1565: [NOI2009]植物大战僵尸
Description Input Output 仅包含一个整数,表示可以获得的最大能源收入.注意,你也可以选择不进行任何攻击,这样能源收入为0. Sample Input 3 2 10 0 20 0 ...
- BZOJ1565——[NOI2009]植物大战僵尸
1.题意:有一些点,点与点之间有保护关系,每个点都有一个权值,求能获得的最大值 2.分析:裸的最大权闭合图,用网络流进行求解,然后我们发现点与点之间的保护关系可能构成环,这样网络流是无法处理的,然后我 ...
- 【bzoj1565】 NOI2009—植物大战僵尸
http://www.lydsy.com/JudgeOnline/problem.php?id=1565 (题目链接) 题意 给出$n*m$的棋盘,僵尸攻击每个格子可以获得$v$的分数,每个格子又会保 ...
- 【bzoj1565】[NOI2009]植物大战僵尸
1565: [NOI2009]植物大战僵尸 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 2164 Solved: 1001[Submit][Stat ...
- 图论(网络流):COGS 410. [NOI2009] 植物大战僵尸
410. [NOI2009] 植物大战僵尸 ★★★ 输入文件:pvz.in 输出文件:pvz.out 简单对比时间限制:2 s 内存限制:512 MB [问题描述] Plants vs ...
- P2805 [NOI2009]植物大战僵尸
题目地址:P2805 [NOI2009]植物大战僵尸 最大权闭合子图 若有向图 \(G\) 的子图 \(V\) 满足: \(V\) 中顶点的所有出边均指向 \(V\) 内部的顶点,则称 \(V\) 是 ...
- COGS410. [NOI2009] 植物大战僵尸
410. [NOI2009] 植物大战僵尸 ★★★ 输入文件:pvz.in 输出文件:pvz.out 简单对比时间限制:2 s 内存限制:512 MB [问题描述] Plants vs ...
- BZOJ 1565: [NOI2009]植物大战僵尸
1565: [NOI2009]植物大战僵尸 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 2317 Solved: 1071[Submit][Stat ...
- 【刷题】BZOJ 1565 [NOI2009]植物大战僵尸
Description Plants vs. Zombies(PVZ)是最近十分风靡的一款小游戏.Plants(植物)和Zombies(僵尸)是游戏的主角,其中Plants防守,而Zombies进攻. ...
随机推荐
- poj2376 Cleaning Shifts 区间贪心
题目大意: (不说牛了) 给出n个区间,选出个数最少的区间来覆盖区间[1,t].n,t都是给出的. 题目中默认情况是[1,x],[x+1,t]也是可以的.也就是两个相邻的区间之间可以是小区间的右端与大 ...
- CXF-JAX-WS开发(一)入门案例
一.Web Service 1.定义 W3C定义,Web服务(Web service)应当是一个软件系统,用以支持网络间不同机器的互动操作. 2.作用 多系统间数据通信 二.CXF是什么? CXF是目 ...
- YTBro Video 2016-07-30 Sat
明日天气:多云转阴,32~24度 运动向 健身 20中极致疯狂的俯卧撑,新手请勿尝试 跑酷 大神放大招,招招见血,不信你看 赛事 2016年世界室内田径锦标赛 男子4×400接力决赛 台球 RP集中爆 ...
- js-循环执行一个函数
js里的两个内置函数:setInterval()与setTimeout()提供了定时的功能,前者是每隔几秒执行一次,后者是延迟一段时间执行一次.javascript 是一个单线程环境,定时并不是很准, ...
- Js 字符串中提取数字
一 parseInt()方法: 首先想到的是js提供的parseInt方法,例子: var str ="4500元"; var num = parseInt(str); alert ...
- Linux删除大于/小于固定大小的文件等
删除目录下大小为0的文件 rm -f 删除当前目录下面所有 test 文件夹下面的文件 find ./ -name "test" -type d -exec rm -rf {} ; ...
- javascript 数组 常用方法
前言 学学忘忘 闲来做个笔记 整理下数组常用方法. Array 数组常用方法 创建数组的基本方式有两种 1.第一种是使用Array构造函数, var arr = new Array(); ...
- [Ynoi2011]D2T1
题目大意: 给定一个数列$a$,有以下几种询问: 1. 给定$x$,在序列末尾插入$x$.2. 给定$l,r$,输出$\sum\limits_{i=l}^r a_i$.3. 给定$x$,将数列中的所有 ...
- node源码详解(五)
本作品采用知识共享署名 4.0 国际许可协议进行许可.转载保留声明头部与原文链接https://luzeshu.com/blog/nodesource5 本博客同步在https://cnodejs.o ...
- 2015多校联合训练第一场Tricks Device(hdu5294)
题意:给一个无向图,给起点s,终点t,求最少拆掉几条边使得s到不了t,最多拆几条边使得s能到t 思路: 先跑一边最短路,记录最短路中最短的边数.总边数-最短边数就是第二个答案 第一个答案就是在最短路里 ...