1565: [NOI2009]植物大战僵尸

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 2161  Solved: 1000
[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

 

[Submit][Status][Discuss]

HOME Back

————————————————我是分割线——————————————————————————

好题啊好题

这题折腾了三天,差点没吐出血来。

先拓扑排序求环,把环删掉。

之后重建图求最大权闭合子图,把一个植物向保护它的植物连边,跑一遍网络流即可。

第一次只过了4个点。不明所以。

换方法重写了拓扑,在网络流中加限制乱搞。

终于90,但第九个点一直RE,最后发现数组开小了。这题最多600个点,但边数组一直开到800005才A了。TAT~

 /*
Problem: bzoj 1565 [NOI2009]植物大战僵尸
OJ: bzoj
User: S.B.S.
Time: 264 MS
Memory: 13884 KB
Length: 6934 B
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstdlib>
#include<iomanip>
#include<cassert>
#include<climits>
#include<functional>
#include<bitset>
#include<vector>
#include<list>
#define F(i,j,k) for(int i=j;i<=k;++i)
#define M(a,b) memset(a,b,sizeof(a))
#define FF(i,j,k) for(int i=j;i>=k;i--)
#define inf 0x3f3f3f3f
#define maxm 1001
#define mod 998244353
//#define LOCAL
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;
}
int n,m;
int mp[];
struct EDGE
{
int from;
int to;
int value;
int next;
}e[];
int head[];
int v[],in[],out[];
int tot=;
inline void addedge(int u,int v,int w)
{
e[++tot].from=u;
e[tot].to=v;
e[tot].value=w;
e[tot].next=head[u];
head[u]=tot;
// tot++;
}
//bool kan[2000][2000];
int ans=;
//inline int at(int x,int y)
//{
// return m*x+y+1;
//}
//int stk[4001],top=0;
//inline void topsort()
//{
// int temp[4001];M(temp,0);
// F(i,1,m*n) temp[i]=in[i];
// F(i,1,m*n){
// if(in[i]==0){
// stk[top]=i;
//// cout<<i<<"********"<<endl;
// top++;
// }
// }
//// cout<<top<<": "<<endl;
//// F(i,0,top-1) cout<<stk[i]<<" ";cout<<endl;
// while(top!=0){
// top--;int u=stk[top];
// for(int i=head[u];i!=-1;i=e[i].next)
// {
// in[e[i].to]--;
// if(in[e[i].to]==0){
// stk[top]=e[i].to;
// top++;
// }
// }
// }
// F(i,1,m*n){
// if(in[i]!=0){
// stk[top]=i;
// top++;
// }
// }
// while(top!=0){
// top--;int u=stk[top];
// temp[u]=-1;out[u]=-1;
// v[u]=0;
// }
// F(i,1,m*n) in[i]=temp[i];
// return;
//}
inline void add(int u,int v,int w)
{
addedge(u,v,w);
addedge(v,u,);
++in[u];
return;
}
int map[];
int S,T;
bool ok()
{
F(i,S,T) if(map[i]!=-) map[i]=-;
int que[];
int hd=,tl=;
que[tl++]=S;
map[S]=;
while (hd<tl){
int u=que[hd++];
for(int i=head[u];i;i=e[i].next)
{
if(map[e[i].to]==-&&e[i].value)
{
map[e[i].to]=map[u]+;
que[tl++]=e[i].to;
}
}
}
// if (map[T]!=-1) return true;
// else return false;
return map[T]>;
}
int cur[];
int zeng(int k,int now)
{
if (k==T) return now;
int r=;
for (int i=cur[k];i&&now>r;i=e[i].next)
{
if (map[k]+==map[e[i].to]&&e[i].value)
{
int t=zeng(e[i].to,min(now-r,e[i].value));
e[i].value-=t;e[i^].value+=t;r+=t;
if(e[i].value) cur[k]=i;//***
// cout<<e[i].from<<" ---> "<<e[i].to<<" $ "<<t<<endl;
}
}
if (!r) map[k]=-;
return r;
}
int dinic()
{
int r=,t;
M(cur,);
while (ok()){
for(int i=S;i<=T;++i) cur[i]=head[i];
r+=zeng(S,inf);
// while(t=zeng(S,inf)) r+=t;
}
return r;
}
//pair<int,int> kk[4001];
//int cur;
int main()
{
std::ios::sync_with_stdio(false);//cout<<setiosflags(ios::fixed)<<setprecision(1)<<y;
#ifdef LOCAL
freopen("111.in","r",stdin);
freopen("data.out","w",stdout);
#endif
cin>>n>>m;
S=;T=m*n+;
M(mp,);M(head,);
// F(i,0,n-1)F(j,0,m-1){
// int x,y;
// cin>>x>>y;
// mp[i][j]=x;
// v[at(i,j)]=x;
// in[at(i,j)]++;
// if(j==m-1) in[at(i,j)]--;
// if(j!=0) add(at(i,j),at(i,j-1),v[at(i-1,j)]);
// if(y==0) continue;
//// **********************************************
// F(k,1,y){
// int a,b;
// cin>>a>>b;
// kk[cur].first=at(i,j);
// kk[cur].second=at(a,b);
// cur++;
// in[at(a,b)]++;
// addedge(at(i,j),at(a,b),0);
//// cout<<at(i,j)<<" "<<at(a,b)<<" &&&&&"<<endl;
// }
// }
// F(i,1,m*n) cout<<in[i]<<" ";cout<<endl;
// cout<<"/*****************************"<<endl;
// F(i,1,tot) cout<<e[i].from<<" ---> "<<e[i].to<<" $ "<<e[i].value<<endl;
// cout<<"*****************************/"<<endl;
F(i,,n*m){
int temp;
cin>>mp[i];
if(mp[i]>) add(S,i,mp[i]);
else add(i,T,-mp[i]);
cin>>temp;
while(temp--){
int x,y;
cin>>x>>y;
add(x*m+y+,i,inf);
}
if(i%m) add(i,i+,inf);
}
// topsort();
// cout<<"))))))"<<endl;
// F(i,1,m*n) if(in[i]==-1) cout<<i<<" ";cout<<"((((("<<endl;
// M(e,0);M(head,-1);tot=0;
int q[];M(q,);
int cur1=,cur2=;
for(int i=S;i<=T;++i){
if(!in[i]) q[cur2++]=i;
map[i]=-;
}
int sum=;
while(cur1<cur2){
int cnt=q[cur1++];map[cnt]=;
if(mp[cnt]>) sum+=mp[cnt];
for(int i=head[cnt];i;i=e[i].next)
{
if(i&) if(!--in[e[i].to]) q[cur2++]=e[i].to;
}
}
// F(i,1,m*n) cout<<in[i]<<" ";cout<<endl;
// cout<<"v: "<<endl;
// F(i,1,m*n) cout<<v[i]<<" ";cout<<endl;
// F(i,0,n-1)F(j,0,m-1){
// if(in[at(i,j)]==-1) continue;
//// cout<<at(i,j)<<" : "<<in[at(i,j)]<<"@ "<<endl;
// if(j!=0&&in[at(i,j-1)]!=-1) add(at(i,j-1),at(i,j),inf);
// if(v[at(i,j)]==0) continue;
// if(v[at(i,j)]>0) add(31,at(i,j),v[at(i,j)]),sum+=v[at(i,j)];
// else add(at(i,j),32,-v[at(i,j)]);
// }
// while(cur!=0){
// cur--;
// if(in[kk[cur].first]==-1||in[kk[cur].second]==-1) continue;
// int u=kk[cur].first;
// int v=kk[cur].second;
// add(v,u,inf);
// }
// cout<<"/*****************************"<<endl;
// F(i,1,tot) cout<<e[i].from<<" ---> "<<e[i].to<<" $ "<<e[i].value<<endl;
// cout<<"*****************************/"<<endl;
// cout<<sum<<endl;
cout<<sum-dinic()<<endl;
return ;
}
/*
3 2
10 0
20 0
-10 0
-5 1 0 0
100 1 2 1
100 0
*/

植物大战僵尸

bzoj 1565 [NOI2009]植物大战僵尸 解题报告的更多相关文章

  1. BZOJ 1565: [NOI2009]植物大战僵尸( 最小割 )

    先拓扑排序搞出合法的, 然后就是最大权闭合图模型了.... --------------------------------------------------------------------- ...

  2. Bzoj 1565: [NOI2009]植物大战僵尸 最大权闭合图,拓扑排序

    题目: http://cojs.tk/cogs/problem/problem.php?pid=410 410. [NOI2009] 植物大战僵尸 ★★★   输入文件:pvz.in   输出文件:p ...

  3. 洛谷 P2805 [NOI2009]植物大战僵尸 解题报告

    P2805 [NOI2009] 植物大战僵尸 题目描述 Plants vs. Zombies(PVZ)是最近十分风靡的一款小游戏.Plants(植物)和Zombies(僵尸)是游戏的主角,其中Plan ...

  4. BZOJ 1565 [NOI2009]植物大战僵尸 | 网络流

    传送门 BZOJ 1565 题解 这道题也是个经典的最大权闭合子图-- 复习一下最大权闭合子图是什么? 就是一个DAG上,每个点有个或正或负的点权,有的点依赖于另外一些点(如果选这个点,则被依赖点必选 ...

  5. BZOJ 1565 NOI2009 植物大战僵尸 topo+最小割(最大权闭合子图)

    题目链接:https://www.luogu.org/problemnew/show/P2805(bzoj那个实在是有点小小的辣眼睛...我就把洛谷的丢出来吧...) 题意概述:给出一张有向图,这张有 ...

  6. BZOJ 1565: [NOI2009]植物大战僵尸(网络流+缩点)

    传送门 解题思路 最大权闭合子图.但是要注意一些细节,假如有一堆植物形成一个环,那么这些植物都是无敌的,并且他们保护的植物是无敌的,他们保护的保护的植物是无敌 的.所以要缩点,然后拓扑排序一次判无敌, ...

  7. bzoj 1565 [NOI2009]植物大战僵尸【tarjan+最大权闭合子图】

    一上来以为是裸的最大权闭合子图,上来就dinic -然后没过样例.不得不说样例还是非常良心的给了一个强连通分量,要不然就WA的生活不能自理了 然后注意到有一种特殊情况:每个植物向他保护的植物连边(包括 ...

  8. 1565: [NOI2009]植物大战僵尸 - BZOJ

    Description Input Output仅包含一个整数,表示可以获得的最大能源收入.注意,你也可以选择不进行任何攻击,这样能源收入为0.Sample Input3 210 020 0-10 0 ...

  9. BZOJ 1565: [NOI2009]植物大战僵尸

    1565: [NOI2009]植物大战僵尸 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 2317  Solved: 1071[Submit][Stat ...

随机推荐

  1. python和redis简单交互

    python和redis简单交互 1.安装redis模块 pip3 install redis 2.redis模块简单使用: # /usr/bin/env python3 import redis c ...

  2. java技术选型

    综述 JDK版本:JDK8/JDK7 + OracleJDK/OpenJDK Java开发框架:Spring Boot/Spring + Hibernate/MyBatis 前后端分离:单页应用/模板 ...

  3. ref:Mysql授权远程登陆

    ref:https://blog.csdn.net/qq_26710805/article/details/79776897 在Windows环境上操作.步骤如下: 1. 打开cmd窗口,登陆mysq ...

  4. JAVAEE——BOS物流项目02:学习计划、动态添加选项卡、ztree、项目底层代码构建

    1 学习计划 1.jQuery easyUI中动态添加选项卡 2.jquery ztree插件使用 n 下载ztree n 基于标准json数据构造ztree n 基于简单json数据构造ztree( ...

  5. JAVA 获取分行符

    public static final String CR_LF = System.getProperty("os.name").startsWith("Windows& ...

  6. NetCore+Dapper WebApi架构搭建(三):添加实体和仓储

    上一节讲了类库添加一些底层的基本封装,下面来添加实体和仓储 1.Entities文件夹添加一个实体类Users,继承BaseModel,即拥有BaseModel的主键 using System; na ...

  7. Django url 标签和reverse()函数的使用(转)

    使用url标签和reverse()函数,可以避免在模板和view中对url进行硬编码,这样即使url改变了,对模板和view也没有影响, 其实在模板, view中,如果想获取当前访问的url,那用re ...

  8. 【HDU 3662】3D Convex Hull

    http://acm.hdu.edu.cn/showproblem.php?pid=3662 求给定空间中的点的三维凸包上有多少个面. 用增量法,不断加入点,把新加的点能看到的面都删掉,不能看到的面与 ...

  9. luoguP4466 [国际集训队]和与积 莫比乌斯反演

    自然想到枚举\(gcd(a, b)\),不妨设其为\(d\),并且\(a = di, b = dj(a > b)\) 那么\(\frac{ab}{a + b} = \frac{dij}{i + ...

  10. bzoj 1176: [Balkan2007]Mokia&&2683: 简单题 -- cdq分治

    2683: 简单题 Time Limit: 50 Sec  Memory Limit: 128 MB Description 你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要 ...