1565: [NOI2009]植物大战僵尸

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 1972  Solved: 917
[Submit][Status][Discuss]

Description

Input

Output

仅包含一个整数,表示可以获得的最大能源收入。注意,你也可以选择不进行任何攻击,这样能源收入为0。

Sample Input

3 2
10 0
20 0
-10 0
-5 1 0 0
100 1 2 1
100 0

Sample Output

25

HINT

在样例中, 植物P1,1可以攻击位置(0,0), P2, 0可以攻击位置(2,1)。 
一个方案为,首先进攻P1,1, P0,1,此时可以攻击P0,0 。共得到能源收益为(-5)+20+10 = 25。注意, 位置(2,1)被植物P2,0保护,所以无法攻击第2行中的任何植物。 
【大致数据规模】
约20%的数据满足1 ≤ N, M ≤ 5;
约40%的数据满足1 ≤ N, M ≤ 10;
约100%的数据满足1 ≤ N ≤ 20,1 ≤ M ≤ 30,-10000 ≤ Score ≤ 10000 。

Source

Solution

一开始想到的是,在网格图上加限制然后搞搞,发现其实不对,因为能吃掉的植物和网格什么的无关,而是和植物们的攻击有关

很容易想到,如果一个植物被另一个植物保护,那么必须吃掉另一个植物,才能吃掉这个植物,所以,很显然顺序是需要考虑的,但又发现,如果多个植物可以互相保护(也就是连成环,很显然这些植物都是无敌的RMB玩家)

这种类型很容易就联想到最小割模型(最大权闭合子图),又因为环上植物无敌,所以不去考虑环上植物,那么把环上的扔掉即可

开始想写Tarjan,写完后发现不行,于是换拓扑排序,然后发现太久太久没写过了,竟然快忘了....

这里可以直接建网络流图,拓扑一遍,在增广的时候加限制即可.(不过需要一些特殊的技巧)

或者先对保护的点连边,拓扑一遍,然后再建新图跑网络流即可 值得注意的是:保护的点需要加上它左边的点(很显然僵尸不能跳过一个植物吃后面的)

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
int read()
{
int x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
#define maxn 1000
#define maxm 1000010
int n,m,total,score[maxn];
struct EdgeNode{int next,to,cap;}edge[maxm];
int head[maxn],cnt=;
void addedge(int u,int v,int w) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v; edge[cnt].cap=w;}
void insertedge(int u,int v,int w) {addedge(u,v,w); addedge(v,u,);} struct RoadNode{int next,to;}road[maxm>>];
int last[maxn],tot;
void addroad(int u,int v) {tot++; road[tot].next=last[u]; last[u]=tot; road[tot].to=v;}
void insertroad(int u,int v) {addroad(u,v);}
bool visit[maxn]; int du[maxn],s,t;
void Paint(int now)
{
visit[now]=;
for (int i=last[now]; i; i=road[i].next)
if (!visit[road[i].to]) Paint(road[i].to);
}
void TopoSort()
{
s=,t=n*m;
stack<int>st;
for (int i=s; i<=t; i++) if (!du[i]) st.push(i); else visit[i]=;
while (!st.empty())
{
int now=st.top(); st.pop(); visit[now]=;
for (int i=last[now]; i; i=road[i].next)
{
du[road[i].to]--;
if (!du[road[i].to]) st.push(road[i].to);
}
//printf("%d\n",now);
}
for (int i=s; i<=t; i++) if (visit[i]) Paint(i);
}
int dis[maxn],cur[maxn],S,T;
#define inf 0x7fffffff
bool bfs()
{
queue<int>q;
for (int i=S; i<=T; i++) dis[i]=-;
q.push(S); dis[S]=;
while (!q.empty())
{
int now=q.front(); q.pop();
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].cap && dis[edge[i].to]==-)
dis[edge[i].to]=dis[now]+,q.push(edge[i].to);
}
return dis[T]!=-;
}
int dfs(int loc,int low)
{
if (loc==T) return low;
int w,used=;
for (int i=cur[loc]; i; i=edge[i].next)
if (edge[i].cap && dis[edge[i].to]==dis[loc]+)
{
w=dfs(edge[i].to,min(low-used,edge[i].cap));
edge[i].cap-=w; edge[i^].cap+=w; used+=w;
if (used==low) return low; if (edge[i].cap) cur[loc]=i;
}
if (!used) dis[loc]=-;
return used;
}
int dinic()
{
int tmp=;
while (bfs())
{
for (int i=S; i<=T; i++) cur[i]=head[i];
tmp+=dfs(S,inf);
}
return tmp;
}
void Build()
{
S=,T=n*m+;
for (int i=; i<=n*m; i++)
if (!visit[i])
{
if (score[i]>) insertedge(i,T,score[i]); else insertedge(S,i,-score[i]);
for (int j=last[i]; j; j=road[j].next)
if (!visit[road[j].to]) insertedge(i,road[j].to,inf);
total+=score[i]>?score[i]:;
}
}
int locate(int x,int y) {return (x-)*m+y;}
int main()
{
n=read(),m=read();
for (int i=; i<=n; i++)
for (int j=; j<=m; j++)
{
int now=locate(i,j),num;
score[now]=read(); num=read();
for (int x,y,k=; k<=num; k++)
x=read()+,y=read()+,insertroad(now,locate(x,y)),du[locate(x,y)]++;
if (j>) insertroad(now,locate(i,j-)),du[locate(i,j-)]++;
}
TopoSort();
Build();
int maxflow=dinic();// printf("%d %d\n",total,maxflow);
printf("%d\n",total-maxflow);
return ;
}

一写这种需要重构图的,用上road啊last,tot啊什么的,总会莫名其妙的写混...还要肉眼对拍浪费时间

【BZOJ-1565】植物大战僵尸 拓扑排序 + 最小割的更多相关文章

  1. P2805 [NOI2009]植物大战僵尸 (拓扑排序 + 最小割)

    题意:N*M的矩阵 每个点上都有一颗植物 僵尸只能从每一行的最右边向左进攻 每个植物有攻击范围 可以保护在攻击范围内的植物 同时每一颗植物也保护他左边的植物 摧毁每个植物能获得价值 如果这个植物被保护 ...

  2. BZOJ 1565 植物大战僵尸(拓扑排序+最大权闭合子图)

    图中的保护关系就类似于最大权闭合子图.即你想杀x,你就一定要杀掉保护x的点,那么把x向保护它的点连边.那么题目就转化成了最大权闭合子图的问题. 但是这个图有点特殊啊... 考虑有环的情况,显然这个环以 ...

  3. 洛谷2805 [NOI2009]植物大战僵尸 (拓扑排序+最小割)

    坚决抵制长题面的题目! 首先观察到这个题目中,我们会发现,我们对于原图中的保护关系(一个点右边的点对于这个点也算是保护) 相当于一种依赖. 那么不难看出这个题实际上是一个最大权闭合子图模型. 我们直接 ...

  4. BZOJ 1565 植物大战僵尸(最大权闭合图)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1565 题意:植物大战僵尸,一个n*m的格子,每 个格子里有一个植物,每个植物有两个属性: ...

  5. BZOJ 1565 植物大战僵尸 最大权闭合子图+网络流

    题意: 植物大战僵尸,一个n*m的格子,每 个格子里有一个植物,每个植物有两个属性: (1)价值: (2)保护集合,也就是这个植物可以保护矩阵中的某些格子. 现在你是僵尸,你每次只能从(i,m) 格子 ...

  6. 【bzoj1565】[NOI2009]植物大战僵尸 拓扑排序+最大权闭合图

    原文地址:http://www.cnblogs.com/GXZlegend/p/6808268.html 题目描述 输入 输出 仅包含一个整数,表示可以获得的最大能源收入.注意,你也可以选择不进行任何 ...

  7. [BZOJ 3774] 最优选择 【最小割】

    题目链接:BZOJ - 3774 题目分析 此题与“文理分科”那道题目有些类似.都是使用最小割来求解,先加上可能获得的权值,在减掉必须舍弃的权值(最小割). 文理分科是规定每个人和 S 连就是选文,和 ...

  8. [BZOJ 2007] [Noi2010] 海拔 【平面图最小割(对偶图最短路)】

    题目链接:BZOJ - 2007 题目分析 首先,左上角的高度是 0 ,右下角的高度是 1.那么所有点的高度一定要在 0 与 1 之间.然而选取 [0, 1] 的任何一个实数,都可以用整数 0 或 1 ...

  9. BZOJ 2109 航空管制(拓扑排序+贪心)

    绝世好题啊.. 题意:给出一个DAG,和每个点要求出现在这个DAG里面的拓扑排序的位置<=ti,求出所有可能的拓扑排序里面每个点出现的位置的最小值. 正着做不好做,考虑反着做,建立这个图的反图. ...

随机推荐

  1. js会员头像上传拖动处理头像类

    js会员头像上传拖动处理头像类 点击下载源码文件

  2. PAT 1028. 人口普查(20)

    某城镇进行人口普查,得到了全体居民的生日.现请你写个程序,找出镇上最年长和最年轻的人. 这里确保每个输入的日期都是合法的,但不一定是合理的--假设已知镇上没有超过200岁的老人,而今天是2014年9月 ...

  3. ISAPI_Rewrite中文手册

    参考:http://blog.csdn.net/fanxiaojie119/article/details/5353186 第一章:软件介绍ISAPI_Rewrite 是一款适用于IIS的功能强大的基 ...

  4. JavaScript的一些知识碎片(1)

    打算把使用Javascript的水平从child提升到小学毕业,近期会持续记录一些知识点. javascript的引用机制:只要一个对象赋值为另一个对象,就建立了引用.一旦建立了引用,对象们就公用一块 ...

  5. 翻译qmake文档(四) Building Common Project Types

    翻译qmake文档 目录 本章原英文文档:http://qt-project.org/doc/qt-5/qmake-common-projects.html 构建常见的项目类型        本章描述 ...

  6. 还记得高中的向量吗?leetcode 335. Self Crossing(判断线段相交)

    传统解法 题目来自 leetcode 335. Self Crossing. 题意非常简单,有一个点,一开始位于 (0, 0) 位置,然后有规律地往上,左,下,右方向移动一定的距离,判断是否会相交(s ...

  7. 记一次ASP.NET网站的入侵和如何避免被入侵

    ASP.NET网站入侵第二波(LeaRun.信息化快速开发框架 已被笔者拿下) 详细介绍请看第二波 首先我要申明的是不是什么语言写出来的程序就不安全,而是得看写代码的人如何去写这个程序 前些日子我去客 ...

  8. WEB API 中HTTP的get、post、put,delete 请求方式

    一.WEB API 中HTTP 请求方式的四个主要方法 (GET, PUT, POST, DELETE), 按照下列方式映射为 CURD 操作: 1.POST 用于新建资源,服务端在指定的URI 上创 ...

  9. matlab eps

    matlab eps eps是一个函数.当没有参数时默认参数是1.返回的是该参数的精度. 也就是说单个的eps实际上是eps(1),表示的是1的精度. 这里要说一下精度的概念.浮点数所能表示的数值范围 ...

  10. springMvc发布restFull风格的URL

    package zpark.controller; import org.springframework.stereotype.Controller; import org.springframewo ...