[Luogu 2805] NOI2009 植物大战僵尸
<题目链接>
这题是个比较经典的最大权闭合子图,可以建图转化为最小割问题,再根据最大流最小割定理,采用任意一种最大流算法求得。
对于每个点,如果点权w为正,则从源点到这个点连一条边权为w的有向边;否则如果w为负则从这个点到汇点连一条有向边。加边的时候预处理出反图的每个点入度。
其次,每一个被保护的点到保护它的点连一条边权为INF的有向边。
注意同一行的左侧点受到右侧点的间接保护,因此对于每一个不位于当前行最右的点,都要向其右侧的一个点连一条INF有向边(连一条即可,不必连所有)。
初始化完成后,在反向图(惯用链式前向星的表示,在跑最小割之前,边权为0的边就是反向图的边)上拓扑排序,删去在环中的点,留下有效点。
然后在建的这个图上跑最小割。
最终的答案为:源点到「与源点相连的所有有效点」的边权和减去网络最小割。
建模是个好能力,希望包括我在内的每一个OIer都能通过不懈努力获得。
加油。
#include <algorithm>
#include <climits>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int MAXN=10000,MAXM=900000;
bool exist[MAXN]/*拓扑排序有效点标记*/,vis[MAXN];
int n,m,N,S,T,cnt,ans,head[MAXN],cur[MAXN]/*当前弧*/,inn[MAXN]/*反图入度*/,dis[MAXN]/*层次图*/;
struct edge
{
int nxt,to,w;
}e[MAXM];
void AddEdge(int x,int y,int w)
{
e[++cnt].nxt=head[x];
e[cnt].to=y;
e[cnt].w=w;
head[x]=cnt;
}
void AddEdges(int x,int y,int w)
{
AddEdge(x,y,w);
AddEdge(y,x,0);
++inn[x];//预处理反图入度
}
void T_Sort(int S)
{
queue<int> q;//栈或队列都可以(优先队列或者手写堆其实也没问题)
for(int i=S;i<=T;++i)
if(!inn[i])
q.push(i);//入度为0的入队
while(!q.empty())
{
int x=q.front();
q.pop();
exist[x]=1;
for(int i=head[x],t;i;i=e[i].nxt)
if(!e[i].w && !--inn[t=e[i].to])
q.push(t);
}
for(int i=head[S];i;i=e[i].nxt)
if(!inn[e[i].to])
ans+=e[i].w;//事先累加源点到「与源点相连的所有有效点」的边权
}
bool BFS(int S)
{
queue<int> q;
memset(dis,0,sizeof dis);
memset(vis,0,sizeof vis);
q.push(S);
vis[S]=1;
while(!q.empty())
{
int x=q.front();
q.pop();
for(int i=head[x],t;i;i=e[i].nxt)
if(e[i].w && exist[t=e[i].to] && !vis[t])
{
vis[t]=1;
dis[t]=dis[x]+1;
q.push(t);
}
if(vis[T])//已经处理到汇点就退出
return 1;
}
return 0;
}
int DFS(int x,int k)
{
if(x==T)
return k;
int tmp=0;//这个累加必须有,否则最后一个点会被卡掉。
for(int i=cur[x],t,f;i;i=e[i].nxt)
if(e[i].w && exist[t=e[i].to] && dis[t]==dis[x]+1 && (f=DFS(t,min(k,e[i].w))))
{
cur[x]=i;
e[i].w-=f;//当前边的边权
e[((i-1)^1)+1].w+=f;//反向边的边权
tmp+=f;
k-=f;
}
if(!tmp)
dis[x]=-1;//必须有的操作
return tmp;
}
void Dinic(void)
{
int f;
while(BFS(S))//预处理层次图,直到无法间出层次图
while(memcpy(cur,head,sizeof cur),f=DFS(S,INT_MAX))//跑DFS直到当前层次图上无法增广。
ans-=f;//连接源点的边权和减去最小割
}
int main(int argc,char *argv[])
{
scanf("%d %d",&n,&m);
N=n*m,T=N+1;//N是总点数,T是汇点
for(int i=1,w,k;i<=N;++i)
{
scanf("%d %d",&w,&k);
if(i%m)//如果不是当前行最后一个点,就向右连一条边。
AddEdges(i,i+1,INT_MAX);
if(w>0)
AddEdges(S,i,w);//连源点
else if(w<0)
AddEdges(i,T,-w);//连汇点
for(int j=1,r,c;j<=k;++j)
{
scanf("%d %d",&r,&c);
AddEdges(r*m+c+1,i,INT_MAX);//保护关系
}
}
T_Sort(S);//拓扑排序
Dinic();//最小割
printf("%d",ans);
return 0;
}
谢谢阅读。
[Luogu 2805] NOI2009 植物大战僵尸的更多相关文章
- 图论(网络流):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进攻. ...
- 【bzoj1565】[NOI2009]植物大战僵尸
1565: [NOI2009]植物大战僵尸 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 2164 Solved: 1001[Submit][Stat ...
- 【最大权闭合子图 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—植物大战僵尸
http://www.lydsy.com/JudgeOnline/problem.php?id=1565 (题目链接) 题意 给出$n*m$的棋盘,僵尸攻击每个格子可以获得$v$的分数,每个格子又会保 ...
随机推荐
- Centos7 下nginx nginx-1.13.4 安装
环境:CentOS Linux release 7.3.1611 (Core) Linux localhost.localdomain 3.10.0-514.26.2.el7.x86_64 #1 S ...
- “Hello World!”团队——Alpha发布用户使用报告
博客内容: 1.用户体验报告表 2.用户评论截图 3.总结 一.用户体验报告表 用户使用报告 用户序号 用户姓名(化名) 性别 用户职业 使用频次 用户评论 1 小董 女 文学在读硕士 5 1.游戏界 ...
- Java之I/O流(第1部分)
Java 中的I/O流: 1. 输入/输出流原理: 如下图所示:在 java 程序中,对于数据的输入/输出操作以“流”(Stream)的方式进行:J2SDK 提供了各种各样的“流”类,用来获取不同种类 ...
- ACM 第六天
图论 网络流 最大流 INF(初始值) 路径上权值最小的边,决定流量大小. 流量网络的三个特性: ①流量控制 ②反对称性 ③流量守恒 残余网络:保留了c(e)容量<f(e)流量[可以继续流,因为 ...
- OSG配置失败解决方案
这连续三天都在台式机上配置OSG,总是报各种各样的错. 后来换到笔记本上配置,结果一次性就配置成功了.笔记本和台式机都是WIN10系统,都是VS2013.或许有时候出错就可以换台电脑或者重装系统试试. ...
- Git命令基本操作
本文从以下九个方面,介绍Git命令的基本操作: 一. Git安装 二. Git基本配置 三. 创建Git仓库 四. 获得Git仓库 五. 提交更新 六. 提交历史查看 七. 远程仓库 八. 打Tags ...
- cacti设置redis监控端口
1.在Console->Data Templates中选择Redis的模版 在custom Data中勾选中Port2并保存 2.在Console->Data Input Methods中 ...
- CSS设计指南之CSS三种机制:继承、层叠和特指
一.继承 CSS中的祖先元素也会向后代传递一样东西:CSS属性的值.body元素是所有元素的祖先,所有标签都是它的后代,比如为body元素设置一种字体,那么文档中的所有元素,无论它在层次结构中多么靠下 ...
- C#中的is和as操作符
在C#语言中进行类型转换的操作符is和as.is和as都是强制类型转换,但这两者有什么相同之处和不同之处呢?在使用is和as需要注意哪些事项?下面我们从简单的代码示例去探讨这个简单的问题.注:此博文只 ...
- Activiti5工作流笔记二
流程变量 import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import org.activiti ...