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)}$的代价( ...
随机推荐
- 这半年时间学Mysql的总结
一条sql语句的执行流程 select * from t where id=1 1.mysql执行一条查询语句的流程 1.1客户端输入用户名密码连接mysql服务器 1.2查询这条sql语句有没有对应 ...
- 有关vs2010将c++生成exe文件时出现LINK : fatal error LNK1123: 转换到 COFF 期间失败和环境变量问题
不知怎么本来编译好好的VS2010环境,忽然出现“转换到 COFF 期间失败: 文件无效或损坏”的链接错误.花了好多天,试了好多方法,最终解决了这个问题.现在罗列一下这几种解决方案:方案1:点击“项目 ...
- 腾讯企业邮箱 POP3/SMTP 设置
下午魅族MX2刷完机,原先配置的公司邮箱还要重新配置.有些地方需要改,找到了篇文章,如下: 腾讯企业邮箱支持通过客户端进行邮件管理.POP3/SMTP协议收发邮件服务器地址分别如下.接收邮件服务器:p ...
- python_0基础开始_day03
第三节 一.整形和布尔值的转换 int整型 python3: 全部都是整型 python2: 整型,长整型long 十进制转换二进制 # 将十进制的168转换为二进制 #得出结果 将十进制的168转 ...
- 通过Powershell修改文件默认打开方式
修改原理 详情: Windows下通过注册表修改某个类型文件的默认打开方式和文件图标 脚本详情: Github:Change_default_programs.ps1 描述: 至少在Windows10 ...
- xpath定位的一些方法
- SQL Labs刷题补坑记录(less31-less53)
LESS31: 双引号直接报错,那么肯定可以报错注入,并且也过滤了一些东西,^异或没有过滤,异或真香 -1" and (if(length(database())=8,1,0)) and & ...
- 解决VS2008,重新生成解决方案,很慢
正所谓:“工欲善其事,必先利其器“.我也算是深受其害了,特把经验分享出来为大伙分忧! 在刚来公司的时候,使用的公司提供的VS2008作为开发工具,有一个非常让人不爽的问题,就是在重新编译代码(重新生成 ...
- react解析: render的FiberRoot(三)
react解析: render的FiberRoot(三) 感谢 yck: 剖析 React 源码解析,本篇文章是在读完他的文章的基础上,将他的文章进行拆解和加工,加入我自己的一下理解和例子,便于大家理 ...
- centos部署oracle rac单实例11.2.0.3数据库(使用asm磁盘)
部署oracle rac单实例数据库,需要安装grid和datavase两部分,所以首先创建两个用户oracle和grid,因为不能使用root用户进行安装,在安装之前首先需要修改一些系统参数和安装一 ...