题目地址:P2805 [NOI2009]植物大战僵尸

最大权闭合子图

若有向图 \(G\) 的子图 \(V\) 满足: \(V\) 中顶点的所有出边均指向 \(V\) 内部的顶点,则称 \(V\) 是 \(G\) 的一个闭合子图

若 \(G\) 中的点有点权,则点权和最大的闭合子图称为有向图 \(G\) 的最大权闭合子图

构图方法

建立源点 \(S\) 和汇点 \(T\) ,源点 \(S\) 连所有点权为正的点,容量为该点点权;其余点连汇点 \(T\) ,容量为该点点权的相反数,对于原图中的边 \((x,y)\) ,连边 \((x,y,+inf)\)。

定理

  • 最大权闭合图的点权和 \(=\) 所有正权点权值和 \(–\) 最小割。
  • 上述图的最小割包含 \(S\) 到不在最大权闭合图内的正权节点的边和在最大权闭合图内的负权节点到 \(T\) 的边。

推论(最大权闭合图方案)

残量网络中由源点 \(S\) 能够访问到的点,就构成一个点数最少的最大权闭合图。

本题题解

把每个植物当做一个顶点,植物携带的能源数目为顶点的权值。

如果植物 \(b\) 在植物 \(a\) 的攻击范围内,连接一条有向边 \((a,b)\) ,表示 \(a\) 可以保护 \(b\) 。

由于僵尸从右向左进攻,可以认为每个植物都被它右边相邻的植物保护,对于每个植物 \(a\) (除最左边一列),向其左边的相邻植物 \(b\) ,连接一条有向边 \((a,b)\) 。

此时可能有一些植物是互相保护的,都不能被吃掉,这样的点(和与其相连的边)应该全部删掉,拓扑排序一遍即可。

如果要吃掉一个植物,就应该把所有保护它的植物全部吃掉。

对应在图中,如果我们将图转置(即所有边转成其反向边),那么可以吃掉的植物应该构成一个闭合子图,而最优解就是最大权闭合子图。

#include <bits/stdc++.h>
using namespace std;
const int N = 1e4 + 6, M = 1e6 + 6, inf = 1e9;
int n, m, s, t, a[N], ans, d[N], deg[N], v[N];
int Head[N], Edge[M], Leng[M], Next[M], tot = 1;
queue<int> q;
vector<int> e[N];

inline void add(int x, int y, int z) {
    Edge[++tot] = y;
    Leng[tot] = z;
    Next[tot] = Head[x];
    Head[x] = tot;
}

inline bool bfs() {
    memset(d, 0, sizeof(d));
    queue<int> q;
    q.push(s);
    d[s] = 1;
    while (q.size()) {
        int x = q.front();
        q.pop();
        for (int i = Head[x]; i; i = Next[i]) {
            int y = Edge[i], z = Leng[i];
            if (deg[y] || d[y] || !z) continue;
            q.push(y);
            d[y] = d[x] + 1;
            if (y == t) return 1;
        }
    }
    return 0;
}

int dinic(int x, int flow) {
    if (x == t) return flow;
    int rest = flow;
    for (int i = Head[x]; i && rest; i = Next[i]) {
        int y = Edge[i], z = Leng[i];
        if (d[y] != d[x] + 1 || !z) continue;
        int k = dinic(y, min(rest, z));
        if (!k) d[y] = 0;
        else {
            Leng[i] -= k;
            Leng[i^1] += k;
            rest -= k;
        }
    }
    return flow - rest;
}

int main() {
    cin >> n >> m;
    s = n * m, t = s + 1;
    for (int i = 0; i < s; i++) {
        scanf("%d", &a[i]);
        int k;
        scanf("%d", &k);
        while (k--) {
            int x, y;
            scanf("%d %d", &x, &y);
            e[i].push_back(x * m + y);
            ++deg[x*m+y];
        }
    }
    for (int i = 0; i < n; i++)
        for (int j = 1; j < m; j++) {
            e[i*m+j].push_back(i * m + j - 1);
            ++deg[i*m+j-1];
        }
    for (int i = 0; i < s; i++)
        if (!deg[i]) q.push(i), v[i] = 1;
    while (q.size()) {
        int x = q.front();
        q.pop();
        for (unsigned int i = 0; i < e[x].size(); i++) {
            int y = e[x][i];
            if (!v[y] && !--deg[y]) q.push(y), v[y] = 1;
        }
    }
    for (int x = 0; x < s; x++) {
        if (!v[x]) continue;
        for (unsigned int i = 0; i < e[x].size(); i++) {
            int y = e[x][i];
            if (!v[y]) continue;
            add(y, x, inf);
            add(x, y, 0);
        }
        if (a[x] > 0) add(s, x, a[x]), add(x, s, 0), ans += a[x];
        if (a[x] < 0) add(x, t, -a[x]), add(t, x, 0);
    }
    int now = 0;
    while (bfs())
        while ((now = dinic(s, inf)))
            ans -= now;
    cout << ans << endl;
    return 0;
}

P2805 [NOI2009]植物大战僵尸的更多相关文章

  1. 图论(网络流):COGS 410. [NOI2009] 植物大战僵尸

    410. [NOI2009] 植物大战僵尸 ★★★   输入文件:pvz.in   输出文件:pvz.out   简单对比时间限制:2 s   内存限制:512 MB [问题描述] Plants vs ...

  2. COGS410. [NOI2009] 植物大战僵尸

    410. [NOI2009] 植物大战僵尸 ★★★   输入文件:pvz.in   输出文件:pvz.out   简单对比时间限制:2 s   内存限制:512 MB [问题描述] Plants vs ...

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

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

  4. 【刷题】BZOJ 1565 [NOI2009]植物大战僵尸

    Description Plants vs. Zombies(PVZ)是最近十分风靡的一款小游戏.Plants(植物)和Zombies(僵尸)是游戏的主角,其中Plants防守,而Zombies进攻. ...

  5. 【bzoj1565】[NOI2009]植物大战僵尸

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

  6. 【最大权闭合子图 tarjan】bzoj1565: [NOI2009]植物大战僵尸

    dinic+tarjan板子练手题 Description Plants vs. Zombies(PVZ)是最近十分风靡的一款小游戏.Plants(植物)和Zombies(僵尸)是游戏的主角,其 中P ...

  7. BZOJ1565: [NOI2009]植物大战僵尸

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

  8. 【bzoj1565】 NOI2009—植物大战僵尸

    http://www.lydsy.com/JudgeOnline/problem.php?id=1565 (题目链接) 题意 给出$n*m$的棋盘,僵尸攻击每个格子可以获得$v$的分数,每个格子又会保 ...

  9. luogu2805 [NOI2009]植物大战僵尸

    想象一下,要搞掉一个植物,必须先搞掉另一些植物--我们可以发现这是一个最大权闭合子图的问题. 最大权闭合子图的话,太空飞行计划问题是一个入门题,可以一看. 然而我们手玩一下样例就会惊恐地发现,保护关系 ...

随机推荐

  1. OS + Ubuntu ARM Android

    s 1. Ubuntu 18.04 ISO的下载路径参考:https://www.ubuntu.com/download/server/arm 2. Android SDK下载链接:https://p ...

  2. 网络编程基础【day10】:多线程效果演示(二)

    本节内容 1.引子 2.并发多线程效果演示 一.引子 我们说单核的cpu只能同时执行一个任务,但是给我们的一个幻觉是可以执行多个,因为cpu太快了.它是怎么实现的呢?就是上下文切换,它不是轮询着切换的 ...

  3. CentOS7 下编译 Hadoop

    准备工作 下载 Hadoop 源码 Source (当前最新 2.9.2) https://hadoop.apache.org/releases.html 打开压缩包会看到 BUILDING.txt ...

  4. Linux记录-salt-minion安装

    python -m SimpleHTTPServer 8888#!/bin/bash sed -i 's/^#//g' /etc/yum.repos.d/centos7.4.repo sed -i ' ...

  5. 来自Composer中文网安装composer指南

    如果有需要安装composer的童鞋可以参考这个文章配置自己的composer https://pkg.phpcomposer.com/#how-to-install-composer 这里可能会出很 ...

  6. mysql导入导出sql文件,source导入速度慢的解决办法

    1.导出整个数据库mysqldump -u 用户名 -p 数据库名 > 导出的文件名mysqldump -u dbuser -p dbname > dbname.sql2.导出一个表mys ...

  7. hdu 6441 (费马大定理+勾股数 数学)

    题意是给定 n 和 a,问是否存在正整数 b,c 满足:a^n + b^n == c^n.输出 b  c,若不存在满足条件的 b,c,输出 -1 -1. 当 n > 2 时,由费马大定理,不存在 ...

  8. MVC的了解

    MVC是一种架构模式,程序分层,分工合作,各层既相互独立,有协同工作. MVC:Model+View+Controller Model层:业务数据的信息表示,关注支撑业务的信息构成,通常是多个业务实体 ...

  9. 再次回归 Spark-- 转

    原文地址 combineByKey 三个参数 val scores = sc.parallelize(Array(("jake",80.0),("jake",9 ...

  10. 067、如何部署Calico网络 (2019-04-10 周三)

    参考https://www.cnblogs.com/CloudMan6/p/7509975.html   Calico 是一个纯三层的虚拟网络方案,Calico为每个容器分配一个IP,每个host都是 ...