P2805 [NOI2009]植物大战僵尸 + 最大权闭合子图 X 拓扑排序
传送门:https://www.luogu.org/problemnew/show/P2805
题意
有一个n * m的地图,你可以操纵僵尸从地图的右边向左边走,走的一些地方是有能量值的,有些地方会被一些植物保护起来不能走,只有先吃掉特定植物才能走一些地方。求最大可能拿到的能量值和
思路
最大权闭合子图,由于僵尸只能从一行的右边一步一步走到左边,所以每个格子向右边连一条inf的边(表示选了这个点,右边这个点必选),然后有保护的原因,从被保护的格子向保护的格子连一条inf的边。然后就是最大权闭合子图的操作,源点向正权值格子连容量为这个权值的边,负权值的格子向终点连容量为这个权值绝对值的边。
由于图中有环的存在,我们要把环上以及环之后的点都抹去。
然后跑一遍dinic(),算出最小割,用总的正权值 - 这个最小割就是答案。
#include <algorithm>
#include <iterator>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <iomanip>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <stack>
#include <cmath>
#include <queue>
#include <list>
#include <map>
#include <set>
#include <cassert> /* ⊂_ヽ
\\ Λ_Λ 来了老弟
\('ㅅ')
> ⌒ヽ
/ へ\
/ / \\
レ ノ ヽ_つ
/ /
/ /|
( (ヽ
| |、\
| 丿 \ ⌒)
| | ) /
'ノ ) Lノ */ using namespace std;
#define lson (l , mid , rt << 1)
#define rson (mid + 1 , r , rt << 1 | 1)
#define debug(x) cerr << #x << " = " << x << "\n";
#define pb push_back
#define pq priority_queue typedef long long ll;
typedef unsigned long long ull;
//typedef __int128 bll;
typedef pair<ll ,ll > pll;
typedef pair<int ,int > pii;
typedef pair<int,pii> p3; //priority_queue<int> q;//这是一个大根堆q
//priority_queue<int,vector<int>,greater<int> >q;//这是一个小根堆q
#define fi first
#define se second
//#define endl '\n' #define boost ios::sync_with_stdio(false);cin.tie(0)
#define rep(a, b, c) for(int a = (b); a <= (c); ++ a)
#define max3(a,b,c) max(max(a,b), c);
#define min3(a,b,c) min(min(a,b), c); const ll oo = 1ll<<;
const ll mos = 0x7FFFFFFF; //
const ll nmos = 0x80000000; //-2147483648
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f; //
const int mod = 1e9+;
const double esp = 1e-;
const double PI=acos(-1.0);
const double PHI=0.61803399; //黄金分割点
const double tPHI=0.38196601; template<typename T>
inline T read(T&x){
x=;int f=;char ch=getchar();
while (ch<''||ch>'') f|=(ch=='-'),ch=getchar();
while (ch>=''&&ch<='') x=x*+ch-'',ch=getchar();
return x=f?-x:x;
} inline void cmax(int &x,int y){if(x<y)x=y;}
inline void cmax(ll &x,ll y){if(x<y)x=y;}
inline void cmin(int &x,int y){if(x>y)x=y;}
inline void cmin(ll &x,ll y){if(x>y)x=y;} /*-----------------------showtime----------------------*/ const int maxn = ;
int val[maxn],vis[maxn],du[maxn];
vector<int>mp[maxn];
vector<pii>ptt[maxn];//受保护的点。
int n,m;
void topo(){
queue<int>que;
for(int i=; i<=n*m; i++){
if(du[i] == ) que.push(i);
}
while(!que.empty()){
int u = que.front(); que.pop();
vis[u] = ;
for(int i=; i<mp[u].size(); i++){
int v = mp[u][i];
du[v] --;
if(du[v] == ) que.push(v);
}
}
} struct E{
int v,w;
int nxt;
}edge[];
int gtot = , head[maxn];
void addedge(int u,int v,int w){
edge[gtot].v = v;
edge[gtot].w = w;
edge[gtot].nxt = head[u];
head[u] = gtot++; edge[gtot].v = u;
edge[gtot].w = ;
edge[gtot].nxt = head[v];
head[v] = gtot++;
} int dis[maxn],cur[maxn];
bool bfs(int s,int t){
memset(dis, inf, sizeof(dis));
dis[s] = ;
queue<int>que; que.push(s); for(int i=s; i<=t; i++) cur[i] = head[i];
while(!que.empty()){
int u = que.front(); que.pop();
for(int i=head[u]; ~i; i = edge[i].nxt){
int v = edge[i].v, w = edge[i].w;
if(w > && dis[v] > dis[u] + ){
dis[v] = dis[u] + ;
que.push(v);
}
}
}
return dis[t] < inf;
} int dfs(int u,int t,int maxflow){
if(u == t || maxflow == ) return maxflow;
for(int i=cur[u]; ~i; i = edge[i].nxt){
cur[u] = i;
int v = edge[i].v, w = edge[i].w;
if(w > && dis[v] == dis[u] + ) {
int f = dfs(v, t, min(w, maxflow));
if(f > ) {
edge[i].w -= f;
edge[i^].w += f;
return f;
}
}
}
return ;
}
int dinic(int s,int t){
int flow = ;
while(bfs(s, t)){
while(int f = dfs(s,t,inf)) flow += f;
}
return flow;
}
int main(){
memset(head, -, sizeof(head));
scanf("%d%d", &n, &m);
for(int i=; i<=n; i++){
for(int j=; j<=m; j++){
int u = (i-)*m + j, v = u + ;
scanf("%d", &val[u]);
if(j < m){
du[u]++;mp[v].pb(u);//v -> u
}
int q; scanf("%d", &q);
while(q -- ){
int x,y;
scanf("%d%d", &x, &y);
x++,y++;
int p = (x-)*m+y;
du[p]++; mp[u].pb(p);
ptt[u].pb(pii(x,y));
}
}
} int s = , t = n*m+; topo(); int sum = ;
for(int i=; i<=n; i++){
for(int j=; j<=m; j++){ int u = (i-)*m + j, v = u + ;
if(vis[u] == ) continue;
if(j < m && vis[v])addedge(u, v, inf); if(val[u] >= ) addedge(s, u, val[u]), sum += val[u];
else addedge(u, t, -*val[u]); for(int k=; k < ptt[u].size(); k++){
int x = ptt[u][k].fi, y = ptt[u][k].se;
int p = (x - ) * m + y;
addedge(p, u, inf);
}
}
} printf("%d\n", sum - dinic(s,t));
return ;
}
P2805 [NOI2009]植物大战僵尸 + 最大权闭合子图 X 拓扑排序的更多相关文章
- BZOJ 1565 / P2805 [NOI2009]植物大战僵尸 (最大权闭合子图 最小割)
题意 自己看吧 BZOJ传送门 分析 - 这道题其实就是一些点,存在一些二元限制条件,即如果要选uuu则必须选vvv.求得到的权值最大是多少. 建一个图,如果选uuu必须选vvv,则uuu向vvv连边 ...
- 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 1565: [NOI2009]植物大战僵尸 最大权闭合图,拓扑排序
题目: http://cojs.tk/cogs/problem/problem.php?pid=410 410. [NOI2009] 植物大战僵尸 ★★★ 输入文件:pvz.in 输出文件:p ...
- BZOJ 1565 植物大战僵尸 最大权闭合子图+网络流
题意: 植物大战僵尸,一个n*m的格子,每 个格子里有一个植物,每个植物有两个属性: (1)价值: (2)保护集合,也就是这个植物可以保护矩阵中的某些格子. 现在你是僵尸,你每次只能从(i,m) 格子 ...
- 洛谷 P2805 [NOI2009]植物大战僵尸 解题报告
P2805 [NOI2009] 植物大战僵尸 题目描述 Plants vs. Zombies(PVZ)是最近十分风靡的一款小游戏.Plants(植物)和Zombies(僵尸)是游戏的主角,其中Plan ...
- BZOJ 1565 Luogu P2805 [NOI2009]植物大战僵尸 (Tarjan判环、最小割)
我: "立个flag 14点之前调完这题" 洛谷AC时间: 2019-06-24 14:00:16 实力打脸... 网络流板子从来写不对系列 题目链接: (BZOJ) https: ...
- P2805 [NOI2009]植物大战僵尸(最小割+拓扑排序)
题意: n*m的矩阵,每个位置都有一个植物.每个植物都有一个价值(可以为负),以及一些它可以攻击的位置.从每行的最右面开始放置僵尸,僵尸从右往左行动,当僵尸在植物攻击范围内时会立刻死亡.僵尸每到一个位 ...
- 洛谷$P2805\ [NOI2009]$植物大战僵尸 网络流
正解:网络流 解题报告: 传送门$QwQ$ 题面好长昂,,,我大概概括下$QwQ$?有个$n\cdot m$的网格,每个格子有一株植物,击溃一株植物$(x,y)$需要付出$S_{(x,y)}$的代价( ...
随机推荐
- codeforces 322 A Ciel and Dancing
题目链接 题意: 有n个男孩和m个女孩,他们要结对跳舞,每对要有一个女孩和一个男孩,而且其中一个要求之前没有和其他人结对,求出最大可以结多少对. 如图,一条线代表一对,只有这样三种情况. #inclu ...
- Redis Sentinel基本实现原理
一.出现的背景: Redis 主从复制模式下一旦主节点由于故障不能提供服务,需要人工将从节点晋升为主节点,同时还要通知应用方更新主节点地址,对于很多应用这种场景的这种故障处理方式是非常浪费人力的.为了 ...
- JAVA常用的集合类
package com.xian.test; import java.util.ArrayList; import java.util.Enumeration; import java.util.Ha ...
- .c和.h文件的区别
.h文件(头文件): 一般写一些函数声明.宏定义.结构体等内容. 其实就是将各个.c文件中重复的声明.宏定义.结构体,枚举变量等提取出来,放进一个新的文件中,便于其他.c文件共享这部分的代码,同时也方 ...
- 【JDK】JDK源码分析-ReentrantLock
概述 在 JDK 1.5 以前,锁的实现只能用 synchronized 关键字:1.5 开始提供了 ReentrantLock,它是 API 层面的锁.先看下 ReentrantLock 的类签名以 ...
- 利用MAVEN打包可运行jar包,包括依赖的第三方包
转载自:http://bglmmz.iteye.com/blog/2058914 背景: 另一篇文章说了如何利用IDEA来打包,现在来说说如何利用MAVEN打包 目标:应用本身打成一个jar包,依赖的 ...
- Mysql索引进阶入门
1. 索引操作 MySQL 索引 菜鸟 2. 索引类型 PRIMARY 唯一且不能为空:一张表只能有一个主键索引 INDEX 普通索引 UNIQUE 唯一性索引 FULLTEXT 全文索引:用于搜索很 ...
- java并发编程(八)----(JUC)CountDownLatch
CountDownLatch 是一个非常实用的多线程控制工具类." Count Down " 在英文中意为倒计数, Latch 为门问的意思.如果翻译成为倒计数门阀, 我想大家都会 ...
- Unix-IO-同步,异步,阻塞,非阻塞-笔记篇
概念更正 https://www.zhihu.com/question/19732473 错误的四个象限分类 https://www.ibm.com/developerworks/cn/linux/l ...
- react-native 入门基础介绍
目录 安装 项目 主要目录结构 入口 Home模块 Coobook模块 List模块 novel模块 相关参考 一个简单的demo,用于介绍react-native相关基础信息,主要是针对有兴趣的同学 ...