BZOJ 1565 / P2805 [NOI2009]植物大战僵尸 (最大权闭合子图 最小割)
题意
自己看吧 BZOJ传送门
分析
…
这道题其实就是一些点,存在一些二元限制条件,即如果要选uuu则必须选vvv.求得到的权值最大是多少.
建一个图,如果选uuu必须选vvv,则uuu向vvv连边.那么一个点如果要选肯定所有儿子都要选(也就是整棵子数都要选).这就是一个最大权闭合子图的模型.
可以发现,如果一个点数大于1的强连通分量每个点都不可选.那么去挑这些点,同时也可以去掉这些点的祖先.然后就是一个有向无环图.我们选点只要保证选了uuu必须选所有直接相连的儿子就行了.那么就可以用最小割建模来解决.
取到的数的价值之和=所有正数的和-(要舍弃掉的正数的和+要选的负数的和)
我们最小割的任务就是让后面括号中的最小.连边方式为:
- SSS向每个正数连容量为数值的边
- 每个负数向TTT连容量为绝对值的边
- 在我们之前建的关系图中,父亲向每一个儿子连边,容量为∞\infty∞
这样的话:
- 对于正数,分在SSS一边表示选择了,(也就是保留了它连向SSS的那条边),否则割掉这条边表示不选
- 对于负数,分在SSS一边同样表示选择了,(也就是割掉了它连向TTT的那条边),否则保留这条边表示不选
- 因为父亲向儿子连了∞\infty∞的边,那么这条边一定不会被割掉.那么一旦父亲要选,也就是父亲被分在了SSS一边,则儿子一定也会被分在SSS一边,也就是被选择了.因为如果儿子分在TTT那一边,就存在了从S→S\toS→父亲→\to→儿子→T\to T→T的一条增广路,而最小割是不允许这样的情况出现的.
注意细节,这题不是特别难
CODE
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
template<typename T>inline void read(T &num) {
char ch; int flg=1;
while((ch=getchar())<'0'||ch>'9')if(ch=='-')flg=-flg;
for(num=0;ch>='0'&&ch<='9';num=num*10+ch-'0',ch=getchar());
num*=flg;
}
const int MAXN = 605;
const int MAXM = 500005;
const int inf = 1e9;
struct edge { int to, nxt, c, w, C; }e[MAXM];
int n, m, S, T, cnt, fir[MAXN], info[MAXN];
inline void add(int u, int v, int cc) {
e[cnt] = (edge){ v, fir[u], cc }, fir[u] = cnt++;
e[cnt] = (edge){ u, fir[v], 0 }, fir[v] = cnt++;
}
namespace SAP { //最大流
int h[MAXN], gap[MAXN], sz;
int aug(int u, int Max) {
if(u == T) return Max;
int flow = 0, delta, v;
for(int i = info[u]; ~i; i = e[i].nxt)
if(e[i].c && h[v=e[i].to]+1 == h[u]) {
delta = aug(v, min(Max-flow, e[i].c));
e[i].c -= delta, e[i^1].c += delta; info[u] = i;
if((flow+=delta) == Max || h[S] == sz) return flow;
}
if(!(--gap[h[u]])) h[S] = sz;
++gap[++h[u]]; info[u] = fir[u];
return flow;
}
inline int sap() {
memcpy(info, fir, sizeof fir);
int flow = 0; sz = T;
while(h[S] < sz)
flow += aug(S, inf);
return flow;
}
}
int A[MAXN], id[MAXN], sum;
inline int enc(int i, int j) { return (i-1)*m + j; }
vector<int>g[MAXN];
int dfn[MAXN], low[MAXN], scc[MAXN], num[MAXN], stk[MAXN], indx, tmr, tot;
void tarjan(int u) {
dfn[u] = low[u] = ++tmr; stk[++indx] = u;
for(int i = 0, siz = g[u].size(), v; i < siz; ++i)
if(!dfn[v=g[u][i]]) tarjan(v), low[u] = min(low[u], low[v]);
else if(!scc[v]) low[u] = min(low[u], dfn[v]);
if(dfn[u] == low[u]) {
++tot; do{ ++num[tot], scc[stk[indx]] = tot; }while(stk[indx--] != u);
}
}
int vis[MAXN];
int dfs(int u) { //搜索判断子树是否合法
if(vis[u]) return vis[u];
if(num[scc[u]] > 1) return vis[u]=-1;
for(int i = 0, siz = g[u].size(); i < siz; ++i)
if(dfs(g[u][i]) == -1) return vis[u]=-1;
return vis[u]=1;
}
int main () {
memset(fir, -1, sizeof fir);
read(n), read(m);
for(int i = 1, x, y, z; i <= n*m; ++i) { //我是从1~n,1~m标号
read(A[i]), read(z);
while(z--) read(x), read(y), g[enc(x+1, y+1)].push_back(i);
if(i % m) g[i].push_back(i+1); //要先打(x,y+1)的才能打到(x,y)
}
for(int i = 1; i <= n*m; ++i)
if(!dfn[i]) tarjan(i);
tot = 0;
for(int i = 1; i <= n*m; ++i)
if(dfs(i) == 1) id[i] = ++tot; //满足条件就给标号
S = 0, T = tot+1;
for(int i = 1; i <= n*m; ++i) if(id[i]) {
for(int j = 0, siz = g[i].size(); j < siz; ++j)
add(id[i], id[g[i][j]], inf); //父亲如果满足条件,儿子一定也满足
if(A[i] > 0) add(S, id[i], A[i]), sum += A[i];
else if(A[i] < 0) add(id[i], T, -A[i]);
}
printf("%d\n", sum-SAP::sap());
}
BZOJ 1565 / P2805 [NOI2009]植物大战僵尸 (最大权闭合子图 最小割)的更多相关文章
- P2805 [NOI2009]植物大战僵尸 + 最大权闭合子图 X 拓扑排序
传送门:https://www.luogu.org/problemnew/show/P2805 题意 有一个n * m的地图,你可以操纵僵尸从地图的右边向左边走,走的一些地方是有能量值的,有些地方会被 ...
- BZOJ 1565 Luogu P2805 [NOI2009]植物大战僵尸 (Tarjan判环、最小割)
我: "立个flag 14点之前调完这题" 洛谷AC时间: 2019-06-24 14:00:16 实力打脸... 网络流板子从来写不对系列 题目链接: (BZOJ) https: ...
- bzoj1565: [NOI2009]植物大战僵尸 最大权闭合子图,tarjan
bzoj1565: [NOI2009]植物大战僵尸 链接 https://www.lydsy.com/JudgeOnline/problem.php?id=1565 思路 很容易的想到最大权闭合子图 ...
- BZOJ1565[NOI2009]植物大战僵尸——最大权闭合子图+拓扑排序
题目描述 Plants vs. Zombies(PVZ)是最近十分风靡的一款小游戏.Plants(植物)和Zombies(僵尸)是游戏的主角,其中Plants防守,而Zombies进攻.该款游戏包含多 ...
- bzoj 1497 [NOI2006]最大获利【最大权闭合子图+最小割】
不要被5s时限和50000点数吓倒!大胆网络流!我一个5w级别的dinic只跑了1s+! 看起来没有最大权闭合子图的特征--限制,实际上还是有的. 我们需要把中转站看成负权点,把p看成点权,把客户看成 ...
- Bzoj 1565: [NOI2009]植物大战僵尸 最大权闭合图,拓扑排序
题目: http://cojs.tk/cogs/problem/problem.php?pid=410 410. [NOI2009] 植物大战僵尸 ★★★ 输入文件:pvz.in 输出文件:p ...
- BZOJ 1565 植物大战僵尸 最大权闭合子图+网络流
题意: 植物大战僵尸,一个n*m的格子,每 个格子里有一个植物,每个植物有两个属性: (1)价值: (2)保护集合,也就是这个植物可以保护矩阵中的某些格子. 现在你是僵尸,你每次只能从(i,m) 格子 ...
- 【最大权闭合子图 最小割】bzoj1497: [NOI2006]最大获利
最大权闭合子图的模型:今天才发现dinic板子是一直挂的…… Description 新的技术正冲击着手机通讯市场,对于各大运营商来说,这既是机遇,更是挑战.THU集团旗下的CS&T通讯公司在 ...
- 洛谷 P4174 [NOI2006]最大获利 && 洛谷 P2762 太空飞行计划问题 (最大权闭合子图 && 最小割输出任意一组方案)
https://www.luogu.org/problemnew/show/P4174 最大权闭合子图的模板 每个通讯站建一个点,点权为-Pi:每个用户建一个点,点权为Ci,分别向Ai和Bi对应的点连 ...
随机推荐
- java Files 和 Path对文件操作
1.拷贝文件 /** * 拷贝文件,生成新的文件名 * @param pathUpload * @return */ private String converUploadFileName(Strin ...
- oracle数据库与其他数据库区别
本文用的是Oracle 10g数据库,利用PL/SQL Developer的集成开发环境(安装可以自行百度) Oracle数据库 ---> 数据库实例 ---> 表空间(逻辑单位)( ...
- python并发编程之协程(实践篇)
一.协程介绍 协程:是单线程下的并发,又称微线程,纤程.一句话说明什么是线程:协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的. 对于单线程下,我们不可避免程序中出现io操作,但如果我们 ...
- Ettercap 帮助文档
Ettercap(8)帮助 (翻译来自百度翻译,原文附于文后,个人润色) 1.概述 Ettercap-多用途嗅探器/内容过滤器,用于中间人攻击 重要提示 自Ettercap Ng(以前为0.7.0)以 ...
- 1263: 你会做蛋糕吗?(Java)
WUSTOJ 1263: 你会做蛋糕吗? 参考博客 Mitsuha_的博客 Description BobLee是个大吃货,喜欢吃好吃的,也喜欢做好吃的.比如做正方形的蛋糕.比如下图这个5*5的蛋糕. ...
- 1204: 移位运算(C)
一.题目 http://acm.wust.edu.cn/problem.php?id=1204&soj=0 二.分析 无符号短整数关键字为:unsigned short: 无符号短整数长为2字 ...
- asp.net core-6.Bind读取配置文件到C#实例中
1,创建asp.net core web应用程序,选择空网站 2,创建一个appsettings.json文件 为什么要叫appsettings.json呢?因为在Iwebhost启动的时候没有添加任 ...
- .netcore 输出 json 的变量命名格式
从mvc 迁移到的 .netcore mvc 的时候 ,发现很多js 报错,查了一下 居然是变量的大小改变了,这个需要到 starup.cs 设置 //设置返回 json 格式 首字母问题 按原格 ...
- findstr 命令使用
findstr 命令使用 find /? 在文件中搜索字符串. FIND [/V] [/C] [/N] [/I] [/OFF[LINE]] "string" [[drive:][p ...
- 使用cakewalk将工程速度与音频速度对齐(扒带参考)
题外话.cakewalk bandlab版免费 西贝柳斯打谱软件 fisrt版本 免费 (好像限制只能写4个声部) 1选中音频轨中的音频,按住alt+a调出audiosnap. 2点击 根据剪 ...