【BZOJ1565】 植物大战僵尸

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


Solution

  按照依赖关系建立有向图:若清除$a$前必须清除$b$,则连边$a$至$b$。这些依赖关系包括同行植物左边对右边的依赖,以及被保护者对保护者的依赖。

  首先不能考虑开挂集团,也就是依赖关系成强联通分量的植物,也包括能通过依赖关系走到强联通分量的植物——它们都无敌,需要排除掉。这可以用tarjan加上反向边的深搜预处理。

  

  一个植物能够下手,当且仅当其出度为0.

  每一株植物又是带正负权值的,那么明显是要在依赖图中,求一个最大权闭合子图。也就是要有植物起手(迎合闭合的性质,出边都在闭合子图内,即依赖的植物都要一起干掉,都应该在闭合子图的范围内),且干掉的植物权值和最大。

  按照最大权闭合子图的建立方法:源点向所有正权点连容量为其权值的边,所有负权点向汇点连容量为其权值绝对值的边;所有节点按依赖关系连边,容量为$+\infty$。

  答案是所有正权点点权值和减去最大流。能将负权转化为正权来跑网络流的原因,拆拆括号就可以发现,这是很巧妙的。



#include <cstdio>
#include <queue>
#include <vector>
using namespace std;
const int N=610,INF=2147000000;
int n,m,a[N],h[N],hr[N],tot;
int dfn[N],low[N],tmcnt,is[N],st[N],top,ins[N],vis[N];
int S,T,dis[N],cur[N];
int sum;
queue<int> q;
vector<int> list[N];
struct Edge{int v,f,next;}g[1000010];
inline int min(int x,int y){return x<y?x:y;}
inline int id(int x,int y){return (x-1)*m+y;}
inline void addEdge(int u,int v){
    g[++tot].v=v; g[tot].next=h[u]; h[u]=tot;
    g[++tot].v=u; g[tot].next=hr[v]; hr[v]=tot;
}
inline void addEdge(int u,int v,int f){
    g[++tot].v=v; g[tot].f=f; g[tot].next=h[u]; h[u]=tot;
    g[++tot].v=u; g[tot].f=0; g[tot].next=h[v]; h[v]=tot;
}
bool bfs(){
    while(!q.empty()) q.pop();
    q.push(S);
    for(int i=1;i<=T;i++) dis[i]=-1;
    dis[S]=0;
    while(!q.empty()){
        int u=q.front(); q.pop();
        for(int i=h[u],v;i;i=g[i].next)
            if(g[i].f&&dis[v=g[i].v]==-1){
                dis[v]=dis[u]+1;
                if(v==T) return true;
                q.push(v);
            }
    }
    return dis[T]!=-1;
}
int dfs(int u,int delta){
    if(u==T) return delta;
    int ret=0,get;
    for(int i=cur[u],v;i&&delta;i=g[i].next)
        if(g[i].f&&dis[v=g[i].v]==dis[u]+1){
            get=dfs(v,min(delta,g[i].f));
            g[i].f-=get; g[i^1].f+=get;
            if(g[i].f) cur[u]=i;
            delta-=get; ret+=get;
        }
    if(!ret) dis[u]=-1;
    return ret;
}
int dinic(){
    int ret=0;
    while(bfs()){
        for(int i=1;i<=T;i++) cur[i]=h[i];
        ret+=dfs(S,INF);
    }
    return ret;
}
void tarjan(int u,int fa){
    dfn[u]=low[u]=++tmcnt;
    st[++top]=u; ins[u]=1;
    for(int i=h[u],v;i;i=g[i].next){
        v=g[i].v;
        if(!dfn[v]){
            tarjan(v,u);
            low[u]=min(low[u],low[v]);
        }
        else if(ins[v])
            low[u]=min(low[u],dfn[v]);
    }
    if(low[u]==dfn[u]){
        if(st[top]==u){
            ins[u]=0;
            top--;
            return;
        }
        int x;
        do{
            x=st[top--];
            ins[x]=0;
            is[x]=1;
        }while(x!=u);
    }
}
void clear(int u){
    vis[u]=1; is[u]=1;
    for(int i=hr[u],v;i;i=g[i].next)
        if(!vis[v=g[i].v])
            clear(v);
}
int main(){
    freopen("input.in","r",stdin);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            int k=id(i,j),l,x,y;
            scanf("%d%d",&a[k],&l);
            while(l--){
                scanf("%d%d",&x,&y);
                addEdge(id(x+1,y+1),k);
                list[id(x+1,y+1)].push_back(k);
            }
        }
    for(int i=1;i<=n;i++)
        for(int j=1;j<m;j++)
            addEdge(id(i,j),id(i,j+1));
    for(int i=1,up=n*m;i<=up;i++)
        if(!dfn[i])
            tarjan(i,0);
    for(int i=1,up=n*m;i<=up;i++)
        if(!vis[i]&&is[i])
            clear(i);
    for(int i=1,up=n*m;i<=up;i++) h[i]=0;
    tot=1;
    S=n*m+1; T=n*m+2;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            int x=id(i,j);
            if(j<m&&!is[x]&&!is[id(i,j+1)])
                addEdge(x,id(i,j+1),INF);
            if(is[x]) continue;
            if(a[x]>=0){
                addEdge(S,x,a[x]);
                sum+=a[x];
            }
            else addEdge(x,T,-a[x]);
            int sz=list[x].size();
            for(int k=0;k<sz;k++)
                addEdge(x,list[x][k],INF);
        }
    int maxflow=dinic();
    printf("%d\n",sum-maxflow);
    return 0;
}

奇妙代码

  

时间: 2024-08-01 09:34:45

【BZOJ1565】 植物大战僵尸的相关文章

[NOI2009][BZOJ1565] 植物大战僵尸

1565: [NOI2009]植物大战僵尸 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1654  Solved: 769[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

[bzoj1565]植物大战僵尸

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

NOI2009植物大战僵尸

这题应该分两步来做: 1.拓扑排序,去掉无敌点 2.求最大闭合子图 需要注意几点: 1.拓扑排序时,如果(i,j)可以攻击到(x,y),那么增加(x,y)的入度,而不是(i,j)的入度 因为入度代表着要攻击它需要事先攻击几个点 2.求最大闭合子图时,用所有的正权点-最大流 3.求最大闭合子图时,如果(i,j)可以攻击到(x,y),那么连一条边(x,y)到(i,j),容量为正无穷 因为在最大闭合子图中边(x,y)到(i,j)意味着选(x,y)就必须要选(i,j),这与实际含义相符 4.s到正权点,

98植物大战僵尸OL_僵尸迷阵

最近在玩植物大战僵尸Ol打到僵尸迷阵,打了个700分倒数第一,擦.....俗话说的好,失败是成功的妈妈,于是花了点时间写了一个小玩意,我相信下次我一定能拿第一 代码非常简单: using UnityEngine; using System.Collections; using UnityEngine.UI; public class MyScript : MonoBehaviour { // Use this for initialization void Start () { } // Upd

植物大战僵尸2天空之城安卓版发布

全体注意!一大波飞行僵尸正在接近中——中国独创版<植物大战僵尸2天空之城>安卓版终于发布了.超乎想象的空战体验.全新僵尸植物军团.独特闪电环境效果和史无前例的战舰成长系统,让你和戴夫共同肩负守卫天空之城的荣耀重任.赶紧下载游戏,加入云端激战吧. <植物大战僵尸2天空之城>安桌版上线 [中国区独有版本 打造铿锵空战体验] <植物大战僵尸2>即将迎来两周年生日,为感谢中国玩家一直以来的热情支持,EA/PopCap携手拓维游戏打造了这款中国区独有新版本<植物大战僵尸2天

原生JS实现的h5小游戏-植物大战僵尸

代码地址如下:http://www.demodashi.com/demo/12755.html 项目介绍 本项目是利用原生js实现的h5小游戏-植物大战僵尸,主要结合了一下自己对于h5小游戏的理解,结合面向对象的编程思想进行开发,在实现时使用了部分es6语法,对于es6语法不太熟悉的小伙伴可以先查阅相关资料了解一下. 如有需要,可根据自己的需求修改源码样式.源码配置属性代码,实现个性化定制. 以下为文件目录结构示意图,核心代码在js文件夹下的四个common.js.main.js.game.js

java小项目之:植物大战僵尸,这个僵尸有点冷!内附素材源码

Java小项目之:植物大战僵尸! <植物大战僵尸>是由PopCap Games开发的一款益智策略类单机游戏,于2009年5月5日发售,这款游戏可谓是无人不知无人不晓. 在我身边,上到40岁的大叔阿姨,下到7.8岁的小弟弟妹妹都听说和玩过这游戏.在以前智能手机还没流行的时候,各种黑网吧,游戏厅便有着玩这游戏的人.当3G技术现世,半智能手机和智能手机出现后,这款游戏更是如日中天,与愤怒的小鸟一起霸占了手机游戏市场(但当时估计都是盗版的). 相信有些使用b站的小伙伴,应该看过很多这样的视频: 这种视

[转]植物大战僵尸95版技术分析

植物大战僵尸95版不是原版,是由植物大战僵尸吧吧友冥谷川恋制作. 本链接只提供95版的完整压缩包和0-95版的所有exe主程序 压缩包,只玩95版的直接下载95安装包解压即可玩,如果需要玩0-94版,再下载本链接提供的主程序exe压缩包,把其它版本的主程序解压到游戏目录直接运行即可.感谢植吧“崇明人家123”制作提供0-v95僵尸得到了极大强化“我会说我这个版本的冒险一周目都过不去吗?”这个出怪模式非常刺激,需要你强大的pvz功底和运气铁桶铁门.显示隐藏关卡.允许后台运行.刺激的出怪模式.无限制

Bzoj1565 [NOI2009]植物大战僵尸

Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 2363  Solved: 1092 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

bzoj1565【NOI2009】植物大战僵尸

1565: [NOI2009]植物大战僵尸 Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 2034  Solved: 944 [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 Samp