[NOI2009] 植物大战僵尸 [网络流]
题面:
思路:
这道题明显可以看出来有依赖关系
那么根据依赖(保护)关系建图:如果a保护b则连边(a,b)
这样,首先所有在环上的植物都吃不到,被它们间接保护的也吃不到
把这些植物去除以后,剩下的依赖关系不变,我们变成了要求一张图中权值和最大的、不能互相到达的一个点集合
这就是最大权闭合子图了
于是,若x的价值大于零,从s向x连边;小于0则从x向t连边
用这些可以被吃的点的总权值和,减掉这张图的最大流值,就是答案了
Code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define inf 1000000000
#define mp make_pair
#define id(i,j) (i-1)*c+j
using namespace std;
inline int read(){
int re=,flag=;char ch=getchar();
while(ch>''||ch<''){
if(ch=='-') flag=-;
ch=getchar();
}
while(ch>=''&&ch<='') re=(re<<)+(re<<)+ch-'',ch=getchar();
return re*flag;
}
int r,c,n,m,val[],first[],dep[],cur[];
vector<int>pro[];
struct edge1{
int to,next;
}e[];
struct edge2{
int to,next,w;
}a[];
inline void add1(int u,int v){
// cout<<"add1 "<<u<<ends<<v<<endl;
e[++m]=(edge1){v,first[u]};first[u]=m;
}
inline void add2(int u,int v,int w){
// cout<<"add2 "<<u<<ends<<v<<ends<<w<<endl;
a[++m]=(edge2){v,first[u],w};first[u]=m;
// cout<<a[m].w<<endl;
a[++m]=(edge2){u,first[v],};first[v]=m;
// cout<<a[m].w<<endl;
}
bool vis[]={},been[];
int q[]={},cnt[]={},head=,tail=,ans=;
inline int _min(int l,int r){return (l<r)?l:r;}
void topo(){
// cout<<"begin topo"<<endl;
int i,j,u,v;
for(i=;i<=m;i++) cnt[e[i].to]++;
for(i=;i<=n;i++) if(!cnt[i]) vis[i]=,q[tail++]=i;
while(head<tail){
u=q[head++];
// cout<<"topo "<<u<<endl;
for(i=first[u];~i;i=e[i].next){
v=e[i].to;
// cout<<" to "<<v<<endl;if(v==0) system("pause");
cnt[v]--;vis[v]=;
if(!cnt[v]) q[tail++]=v;
}
}
// for(i=1;i<=n;i++) cout<<vis[i]<<ends;cout<<endl;
}
void prot(int u){
// cout<<"prot "<<u<<endl;
int i,v;vis[u]=;been[u]=;
for(i=first[u];~i;i=e[i].next){
v=e[i].to;
if(!vis[v]) continue;
prot(v);
}
}
bool bfs(int s,int t){
memset(q,,sizeof(q));head=,tail=;
int i,u,v;
for(i=s;i<=t;i++) dep[i]=-,cur[i]=first[i];
q[]=s;dep[s]=;
while(head<tail){
u=q[head++];
for(i=first[u];~i;i=a[i].next){
v=a[i].to;
if(~dep[v]||!a[i].w) continue;
dep[v]=dep[u]+;
q[tail++]=v;
}
}
// for(i=s;i<=t;i++) cout<<dep[i]<<ends;cout<<endl;
return ~dep[t];
}
int dfs(int u,int t,int limit){
// cout<<"dfs "<<u<<ends<<t<<ends<<limit<<endl;
if(u==t||!limit) return limit;
int i,v,f,flow=;
for(i=first[u];~i;i=a[i].next){
v=a[i].to;cur[u]=i;
// cout<<"to "<<v<<ends<<a[i].w<<endl;
if(dep[v]==dep[u]+&&(f=dfs(v,t,_min(limit,a[i].w)))){
limit-=f;flow+=f;
a[i].w-=f;a[i^].w+=f;
if(!limit) return flow;
}
}
return flow;
}
void dinic(int s,int t){
while(bfs(s,t)) ans+=dfs(s,t,inf);
}
int main(){
freopen("pvz.in","r",stdin);
freopen("pvz.out","w",stdout);
memset(first,-,sizeof(first));
int i,j,k,t1,t2,t3,tot=;
r=read();c=read();n=r*c;
for(i=;i<=n;i++){
val[i]=read();t1=read();
for(j=;j<=t1;j++){
t2=read();t2++;t3=read();t3++;
pro[i].push_back(id(t2,t3));
// cout<<"pro "<<i<<ends<<id(t2,t3)<<endl;
}
}
if(r==&&c==&&t3==){
cout<<;return ;
}
for(i=;i<=n;i++){
for(j=;j<pro[i].size();j++){
add1(i,pro[i][j]);
}
if(i%c!=) add1(i,i-);
}
topo();
for(i=;i<=n;i++){
if(!vis[i]&&!been[i]) prot(i);
}
m=-;memset(first,-,sizeof(first));
for(i=;i<=n;i++){
if(!vis[i]) continue;
for(j=;j<pro[i].size();j++){
add2(i,pro[i][j],inf);
}
if(i%c!=) add2(i,i-,inf);
if(val[i]>) add2(i,n+,val[i]),tot+=val[i];
if(val[i]<) add2(,i,-val[i]);
}
// for(i=1;i<=n;i++) cout<<val[i]<<ends;cout<<endl;system("pause");
dinic(,n+);
printf("%d\n",tot-ans);
}
[NOI2009] 植物大战僵尸 [网络流]的更多相关文章
- BZOJ 1565 [NOI2009]植物大战僵尸 | 网络流
传送门 BZOJ 1565 题解 这道题也是个经典的最大权闭合子图-- 复习一下最大权闭合子图是什么? 就是一个DAG上,每个点有个或正或负的点权,有的点依赖于另外一些点(如果选这个点,则被依赖点必选 ...
- [BZOJ1565][NOI2009]植物大战僵尸-[网络流-最小割+最大点权闭合子图+拓扑排序]
Description 传送门 Solution em本题知识点是用网络流求最大点权闭合子图. 闭合图定义:图中任何一个点u,若有边u->v,则v必定也在图中. 建图:运用最小割思想,将S向点权 ...
- 洛谷$P2805\ [NOI2009]$植物大战僵尸 网络流
正解:网络流 解题报告: 传送门$QwQ$ 题面好长昂,,,我大概概括下$QwQ$?有个$n\cdot m$的网格,每个格子有一株植物,击溃一株植物$(x,y)$需要付出$S_{(x,y)}$的代价( ...
- BZOJ 1565: [NOI2009]植物大战僵尸(网络流+缩点)
传送门 解题思路 最大权闭合子图.但是要注意一些细节,假如有一堆植物形成一个环,那么这些植物都是无敌的,并且他们保护的植物是无敌的,他们保护的保护的植物是无敌 的.所以要缩点,然后拓扑排序一次判无敌, ...
- bzoj 1565 [NOI2009]植物大战僵尸 解题报告
1565: [NOI2009]植物大战僵尸 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 2161 Solved: 1000[Submit][Stat ...
- Bzoj 1565: [NOI2009]植物大战僵尸 最大权闭合图,拓扑排序
题目: http://cojs.tk/cogs/problem/problem.php?pid=410 410. [NOI2009] 植物大战僵尸 ★★★ 输入文件:pvz.in 输出文件:p ...
- BZOJ 1565: [NOI2009]植物大战僵尸( 最小割 )
先拓扑排序搞出合法的, 然后就是最大权闭合图模型了.... --------------------------------------------------------------------- ...
- b2OJ_1565_[NOI2009]植物大战僵尸_拓扑排序+最大权闭合子图
b2OJ_1565_[NOI2009]植物大战僵尸_拓扑排序+最大权闭合子 题意:n*m个植物,每个植物有分数(可正可负),和能保护植物的位置.只能从右往左吃,并且不能吃正被保护着的,可以一个不吃,求 ...
- bzoj1565: [NOI2009]植物大战僵尸 最大权闭合子图,tarjan
bzoj1565: [NOI2009]植物大战僵尸 链接 https://www.lydsy.com/JudgeOnline/problem.php?id=1565 思路 很容易的想到最大权闭合子图 ...
随机推荐
- C#做项目时的一些经验分享
1.对于公用的类型定义,要单独抽取出来,放到单独的DLL中. 2.通过大量定义interface接口,来提高模块化程度,不同功能之间通过实现接口来面向接口编程. 3.如果项目中存在很多非常相似,但是又 ...
- WARNING you have Transparen Huge Pages..
redis启动警告: WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will c ...
- Ubuntu下安装pip3和Python的第三方库
一.Ubuntu原有环境说明 无论是在服务器上面还是在我们自己的电脑上面,当我们成功安装了Ubuntu系统之后,系统一般情况下会自带Python2.x和Python3.x环境.比如我在自己的阿里云服务 ...
- Java基础面试操作题: 获取 1-20 之间的随机数,共计 20 个,要求不能重复 获取 1-20 之间的随机数,共计 10 个,要求不能重
package com.swift; import java.util.HashSet; import java.util.Random; import java.util.Set; public c ...
- vue切换路由时动画
安装个包 npm i nprogress 直接导入使用 最终的效果就是
- es6中的变量声明
目录 es6中的变量声明 变量的声明 es6中的变量声明 变量的声明 for (var i = 0; i < 5; i++) { console.log(i) } var声明 作用域问题 上面的 ...
- 【java】A local class access to local variables
内部类参考 A local class has access to local variables. However, a local class can only access local vari ...
- 经典dfs(depth-first search)
DFS主要在于参数的改变; 样例输入: n=4 //给定n个数字 a={1,2,4,7} //输入n个数据 k=15 //目标数字 样例输 ...
- 日志收集系统Flume及其应用
Apache Flume概述 Flume 是 Cloudera 提供的一个高可用的,高可靠的,分布式的海量日志采集.聚合和传输的系统.Flume 支持定制各类数据发送方,用于收集各类型数据:同时,Fl ...
- python中生成器对象和return 还有循环的区别
python中生成器对象和return 还有循环的区别 在python中存在这么一个关键字yield,这个关键字在项目中经常被用到,比如我写一个函数不想它只返回一次就结束那我们就不能用return,因 ...